C语言实现简易版三子棋游戏
思路:
我们知道三子棋游戏是横三竖三斜三中只要有一种情况下连起来的字符相同,便视为该用户赢得此次游戏;否则,如果棋盘中再无位置可以放下某一字符,便视为平局。首先,由于本次游戏是用户与电脑PK,所以用户所下的棋我们可以通过键盘输入获得,而电脑所下的棋便可以通过srand()函数和rand()函数随机生成。其次,由于要判断横三竖三斜三所连字符是否相同,这就需要保存用户和电脑每次所下的棋,所以我们可以用一个二维数组来保存。最后,由于电脑是随机生成的坐标,而用户也是结合自身和电脑下棋情况来下棋,所以当用户和电脑各自每走一步后我们都应该判断一下是否其中一方赢了,如果赢了,则结束此次游戏;否则当此二维数组已经存满字符时,则将此次游戏视为平局。
步骤:
- 打印游戏开始菜单(1 表示玩游戏 0表示退出游戏)
- 初始化和打印棋盘
- 玩家走、电脑走(玩家'P' 电脑 'C' 平局 'E' )
- 打印玩家和电脑每走一步后的棋盘
- 判断输赢(玩家'P' 电脑 'C' 平局 'E' 继续' ')
函数介绍:
- 菜单函数
我们约定玩家走一步用'P'表示,电脑走一步用'C'表示,所以可以将棋盘初始化为空格字符' ',简单方便。
//初始化棋盘
void InitArr(char arr[ROW][COL], int row, int col)
{
/*int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
arr[i][j] = ' ';
}
}*/
memset(arr, ' ', row*col);
}
通过查阅工具MSDN我们发现memset()函数有三个参数,第一个参数是一个指向目标变量的指针,第二个参数是表示要设置的字符,第三个参数表示被设置字符的个数。memset()函数的作用是给一个特定的字符设置缓冲区,通俗解释就是说给一个特定的区域设置一个特定的字符。
- 打印棋盘函数
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", arr[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
棋盘打印如下:
- 玩家走函数
由于我们一般输入坐标玩游戏时都是从(1,1)开始,而电脑存储二维数组时是以(0,0)为第一个坐标点,所以当玩家输入坐标时我们应该各自减1。
//玩家走
void Player(char arr[ROW][COL], int row, int col)
{
int x = 0, y = 0;
while (1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if (arr[x - 1][y - 1] == ' ')
{
arr[x - 1][y - 1] = 'P';
break;
}
else
{
printf("坐标已被占用!\n");
}
}
else
{
printf("坐标非法!\n");
}
}
}
- 电脑走函数
我们知道a%b便会得到[0,b)之间的数,所以在知道二维数组行列大小时,利用rand()函数%行(列)就可得到随机坐标。
//电脑走
void Computer(char arr[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (arr[x][y] == ' ')
{
arr[x][y] = 'C';
break;
}
}
}
- 判断输赢函数
//判断棋盘是否满了
int IsFull(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (arr[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
//三子棋的第一种形式
char IsWin(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if ((arr[i][0] == arr[i][1]) && (arr[i][1] == arr[i][2]) && (arr[i][0] != ' '))
{
return arr[i][0];
}
}
for (j = 0; j < col; j++)
{
if ((arr[0][j] == arr[1][j]) && (arr[1][j] == arr[2][j]) && (arr[0][i] != ' '))
{
return arr[0][j];
}
}
if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && (arr[1][1] != ' ')
|| (arr[0][2] == arr[1][1]) && (arr[1][1] == arr[2][0]) && (arr[1][1] != ' '))
{
return arr[1][1];
}
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
//三子棋的第二种形式
char IsWin_1(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 1; j < col - 1; j++)
{
if ((arr[i][j - 1] == arr[i][j]) && (arr[i][j] == arr[i][j + 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
for (j = 0; j < col; j++)
{
for (i = 1; i < row - 1; i++)
{
if ((arr[i - 1][j] == arr[i][j]) && (arr[i][j] == arr[i + 1][j]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if ((arr[i - 1][j - 1] == arr[i][j]) && (arr[i][j] == arr[i + 1][j + 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
if ((arr[i - 1][j + 1] == arr[i][j]) && (arr[i][j] == arr[i + 1][j - 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
//任意几子棋
char IsWin_2(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if ((arr[i][j] == arr[i][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if (j == (col - 1))
{
return arr[i][j];
}
}
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 1; i++)
{
if ((arr[i][j] == arr[i + 1][j]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if (i == (row - 1))
{
return arr[i][j];
}
}
for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
{
if ((arr[i][j] == arr[i + 1][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if ((i == (row - 1)) && (j == (col - 1)))
{
return arr[i][j];
}
for (i = row - 1, j = 0; i > 0, j < col - 1; i--, j++)
{
if ((arr[i][j] == arr[i - 1][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if ((i == 0) && (j == (col - 1)))
{
return arr[i][j];
}
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
源代码如下:
1.game.h
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitArr(char arr[ROW][COL], int row, int col);
void PrintArr(char arr[ROW][COL], int row, int col);
void Player(char arr[ROW][COL], int row, int col);
void Computer(char arr[ROW][COL], int row, int col);
//char IsWin(char arr[ROW][COL], int row, int col);
//char IsWin_1(char arr[ROW][COL], int row, int col);
char IsWin_2(char arr[ROW][COL], int row, int col);
#endif
2.game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘
void InitArr(char arr[ROW][COL], int row, int col)
{
/*int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
arr[i][j] = ' ';
}
}*/
memset(arr, ' ', row*col);
}
//打印棋盘
void PrintArr(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", arr[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
//玩家走
void Player(char arr[ROW][COL], int row, int col)
{
int x = 0, y = 0;
while (1)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if (arr[x - 1][y - 1] == ' ')
{
arr[x - 1][y - 1] = 'P';
break;
}
else
{
printf("坐标已被占用!\n");
}
}
else
{
printf("坐标非法!\n");
}
}
}
//电脑走
void Computer(char arr[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (arr[x][y] == ' ')
{
arr[x][y] = 'C';
break;
}
}
}
//判断棋盘是否满了
int IsFull(char arr[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (arr[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
//三子棋的第一种形式
char IsWin(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if ((arr[i][0] == arr[i][1]) && (arr[i][1] == arr[i][2]) && (arr[i][0] != ' '))
{
return arr[i][0];
}
}
for (j = 0; j < col; j++)
{
if ((arr[0][j] == arr[1][j]) && (arr[1][j] == arr[2][j]) && (arr[0][i] != ' '))
{
return arr[0][j];
}
}
if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && (arr[1][1] != ' ')
|| (arr[0][2] == arr[1][1]) && (arr[1][1] == arr[2][0]) && (arr[1][1] != ' '))
{
return arr[1][1];
}
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
//三子棋的第二种形式
char IsWin_1(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 1; j < col - 1; j++)
{
if ((arr[i][j - 1] == arr[i][j]) && (arr[i][j] == arr[i][j + 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
for (j = 0; j < col; j++)
{
for (i = 1; i < row - 1; i++)
{
if ((arr[i - 1][j] == arr[i][j]) && (arr[i][j] == arr[i + 1][j]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
for (i = 1; i < row - 1; i++)
{
for (j = 1; j < col - 1; j++)
{
if ((arr[i - 1][j - 1] == arr[i][j]) && (arr[i][j] == arr[i + 1][j + 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
if ((arr[i - 1][j + 1] == arr[i][j]) && (arr[i][j] == arr[i + 1][j - 1]) && (arr[i][j] != ' '))
{
return arr[i][j];
}
}
}
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
//任意几子棋
char IsWin_2(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//判断每一行
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 1; j++)
{
if ((arr[i][j] == arr[i][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if (j == (col - 1))
{
return arr[i][j];
}
}
//判断每一列
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 1; i++)
{
if ((arr[i][j] == arr[i + 1][j]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if (i == (row - 1))
{
return arr[i][j];
}
}
//判断正对角线
for (i = 0, j = 0; i < row - 1, j < col - 1; i++, j++)
{
if ((arr[i][j] == arr[i + 1][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if ((i == (row - 1)) && (j == (col - 1)))
{
return arr[i][j];
}
//判断反对角线
for (i = row - 1, j = 0; i > 0, j < col - 1; i--, j++)
{
if ((arr[i][j] == arr[i - 1][j + 1]) && (arr[i][j] != ' '))
{
;
}
else
{
break;
}
}
if ((i == 0) && (j == (col - 1)))
{
return arr[i][j];
}
//判断棋盘是否满了,如果满了则返回'E',否则返回' '
if (IsFull(arr, row, col))
{
return 'E';
}
else
{
return ' ';
}
}
3.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("****************************\n");
printf("****** 1.play ********\n");
printf("****** 0.exit ********\n");
printf("****************************\n");
}
void game()
{
char arr[ROW][COL] = { 0 };
char tmp = 0;
InitArr(arr, ROW, COL);
PrintArr(arr, ROW, COL);
while (1)
{
Player(arr, ROW, COL);
PrintArr(arr, ROW, COL);
printf("\n");
tmp = IsWin_2(arr, ROW, COL);
if (tmp != ' ')
{
break;
}
Computer(arr, ROW, COL);
PrintArr(arr, ROW, COL);
tmp = IsWin_2(arr, ROW, COL);
if (tmp != ' ')
{
break;
}
}
if (tmp == 'P')
{
printf("玩家赢!\n");
}
else if (tmp == 'C')
{
printf("电脑赢!\n");
}
else
{
printf("平局!\n");
}
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
}
int main()
{
test();
system("pause");
return 0;
}