黑白棋的一种。棋盘为3*3大小,只要将自己的三个棋子走成一条线,对方就算输了。
如何实现三子棋?三子棋需要什么? 1.棋盘的建立和显示三子棋的棋盘为3*3大小,通过建立3*3的二维数组,实现对棋子的位置存储。同时通过for循环对二位数组进行打印,实现棋盘的显示。游戏开始时,棋盘上所有的位置应该是空的,所以每次开始游戏时,程序应该对棋盘进行初始化,即将二维数组各个元素的内容设置为“ ”。在打印棋盘时,如果单纯的对数组内容进行打印,会发现打印出来的棋盘和棋子是挤在一起的,非常不直观,所以在打印棋盘时可以额外打印一些 “-” “|” 作为分隔棋盘的标识,代码及效果如下:
void Outputboard(char board[ROW][COL], int row, int col)//打印棋盘
{
int x = 0;
int y = 0;
for (x = 0; x < row; x++)
{
for (y = 0; y < col; y++)
{
printf(" %c ", board[x][y]);
if (y < ROW - 1)
printf("|");
}
printf("n");
if (x < COL - 1)
printf("---|---|---n");
}
}
void freshboard(char board[ROW][COL], int row, int col)//初始化棋盘
{
int x = 0;
int y = 0;
for (x = 0; x < row ; x++)
{
for (y = 0; y < col ; y++)
board[x][y] = ' ';
}
}
2.实现玩家和电脑的落子
落子可以简单的理解为将对应数组内的元素替换为代表玩家和电脑的符号,这里我们设置“#”代表电脑。“*”代表玩家。
要将棋子下在棋盘内,即将对应符号输入数组,需要满足三个条件:一、棋盘内有空位,即数组内还有初始化后的“ ”;二、选择的位置,及对应的数组空间没有被占用;三、选择的位置在棋盘内,即输入的坐标没有超过二维数组范围。满足以上三个条件,才能够正常的下棋。基于以上三个条件,玩家和电脑的行动子函数如下。
void humango(char board[ROW][COL], int row, int col)//玩家行动
{
int x = 0;
int y = 0;
printf("玩家行动n");
printf("请输入坐标->");
while (1)
{
scanf("%d %d", &x, &y);
if (x > 0 && x <= 3 && y > 0 && y <= 3 && board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("输入异常,重新输入->");
}
Outputboard(board, row, col);
}
void comgo(char board[ROW][COL], int row, int col)//电脑行动
{
printf("电脑行动n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
Outputboard(board, row, col);
}
以上代码可以看到,电脑落子的逻辑比玩家落子更为简单,这里电脑并没有添加游戏策略,只是通过使用rand()函数产生的随机数对3取模,实现随机落子。另外,每次落子后都添加了一次棋盘打印,可以使得游戏更为直观。
3、输赢的判断三子棋游戏的结果有三种:电脑赢、玩家赢、平局。
这里先列出三子棋的胜利条件,任意横向三子相同,任意纵向三子相同,任意斜对角之一三子相同,达成以上任意一个条件,即获得游戏胜利,转换为二维数组可以理解为数组内存在任意横向,任意纵向,任意斜对角线存在相同的字符,即可判断胜利。通过判断达成条件的字符类型,简介判断胜者是玩家或者电脑。
平局很好理解,只要当前棋盘的所有位置都被占用,即二维数组的每一个位置都被赋予了“#”或“*”,此时棋盘内没有位置可以继续下棋,同时也没有产生上文说的胜利条件。此时可以判断本局游戏没有赢家,输出平局。
代码如下
int fullboard(char board[ROW][COL], int row, int col)//棋盘下满
{
int x = 0;
int y = 0;
for (x = 0; x < row; x++)
{
for (y = 0; y < col; y++)
if (board[x][y] == ' ')
return 1;//棋盘未满,继续游戏
}
return 0;//棋盘下满,游戏终止
}
char checkboard(char board[ROW][COL], int row, int col)//检查棋盘
{
int x = 0;
int y = 0;
for (x = 0; x < row; x++)
{
if ((board[x][0] == board[x][1]) && (board[x][1] == board[x][2]) && (board[x][0] != ' '))//横向胜利
return board[x][0];
}
for (y = 0; y < col; y++)
{
if ((board[0][y] == board[1][y]) && (board[1][y] == board[2][y]) && (board[0][y] != ' '))//纵向胜利
return board[0][y];
}
if ((((board[0][0] == board[1][1]) && (board[1][1] == board[2][2])) || ((board[0][2] == board[1][1]) && (board[1][1] == board[2][0]))) && (board[1][1] != ' '))//对角线胜利
return board[1][1];
if (fullboard(board,row,col) == 0)//判断平局
return 'F';
else
return 'C';
}
可以看到以上子函数都是int类型,因为我们需要通过他的返回值来判断当前游戏的状态。对于三种胜利条件的判断,我们选择直接返回达成条件的字符,这样可以直观的判断胜利的是哪一方,返回值“F”代表棋盘已满,考虑到会发生在棋盘下满时刚好达成胜利条件这种情况,所以判断平局的优先级在判断胜利条件之后。而当以上情况都不满足时,返回“C”,表示游戏继续进行。
游戏的逻辑和主体的构建明确了我们需要做的内容后,下一步就是完善游戏的逻辑,以保证游戏的正常运行,同时对游戏的主体进行构建。
1、起始界面考虑到三子棋游戏节奏快,周期短,单次运行满足不了实际使用需求,这里建立一个while(1)的无限循环,根据玩家的输入内容,在游戏结束后回到初始界面,在选择退出时再中断循环。这里通过Switch函数,将玩家的输入赋值变量input,对input进行判断,0为退出游戏,即中断循环,1为开始游戏,进入游戏主体,而当玩家没有输入1或0时,提示玩家输入错误,重新输入。
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
char board[ROW][COL] = { 0 };
do
{
menu();
printf("请选择->");
scanf("%d", &input);
switch (input)
{
case 1:
game(board, ROW, COL);
break;
case 0:
printf("游戏结束n");
break;
default:
printf("输入异常,请重试n");
}
} while (input);
return 0;
}
有读者发现函数第一行出现了srand((unsigned int)time(NULL));语句,这条语句的目的是在于调用time()函数配合rand()函数,产生随机值,来保证上文中电脑下棋的随机性,menu()是一个自定义子函数,用于打印交互界面,只需要简单的打印出开始或结束游戏的提示选项即可。
2、游戏主体进入游戏后,游戏进入另一个循环,即玩家和电脑轮流下棋。跳出循环的条件就是任意一方胜利或者双方平局,所以每次玩家或电脑落子,都需要对棋盘状态进行判断,若达成以上三个条件总的任意一个,就可以跳出循环,即结束本局游戏,三种条件都没有达成时,继续游戏。
结束游戏后,需要对本局游戏的结果进行公示,此时对系统返回的内容进行判断,“*”代表玩家胜利,“#”代表电脑利,“F”代表平局。判断结后,需要对结果进行显示,此时通过文字输出结果,并再次打印棋盘状态。
void game(char board[ROW][COL], int row, int col)//游戏主函数
{
char sign = 'C';
freshboard(board, row, col);//初始化棋盘
Outputboard(board, row, col);
while (1)//游戏过程
{
humango(board, row, col);
sign = checkboard(board, row, col);
if (sign != 'C')
break;
comgo(board, row, col);
sign = checkboard(board, row, col);
if (sign != 'C')
break;
}
switch (sign)//判断输赢
{
case '*':
printf("玩家胜利n");
break;
case '#':
printf("电脑胜利n");
break;
case 'F':
printf("平局n");
break;
}
Outputboard(board, row, col);
}
三子棋是黑白棋中棋盘最小,流程最短的游戏种类,我们可以通过对棋盘的拓展,即数组大小的拓展,例如15*15的数组,进行五子棋的设计。相对于三子棋,五子棋的胜负判断要更加复杂,但逻辑上相通。同时,以上代码中,电脑下棋的代码是通过随机值产生的随机位置,没有逻辑性,可以通过对电脑落子的逻辑设计,更加完善整个代码。
以上就是三子棋的c语言实现思路以及流程,各位看官有什么想法或者建议,请不吝赐教。


