三子棋的实现可以分为以下三个步骤:
①游戏的测试逻辑(其代码存放在test.c中);
②游戏的实现逻辑(其代码存放在game.c中);
③游戏实现函数的声明(各个函数的声明存放在game.h中);
其游戏的整体实现思路如下:
1.打印出游戏菜单,输入‘1’开始玩游戏,输入‘0’则退出游戏。
2.打印三子棋的棋盘。
3.玩家以及电脑在棋盘上进行下棋并在每一方下棋后打印棋盘。
4判断胜负或者平局。
5.返回菜单,继续新一轮游戏。
一、作为一款游戏,首先得在屏幕上打印菜单。定义一个名叫menu的函数,其内容显示当输入1时开始玩游戏(PLAY),输入0时退出(EXIT),代码存放在test.c下。
void menu()
{
printf("**************************\n");
printf("***** 1.PLAY *****\n");
printf("***** 0.EXIT *****\n");
printf("**************************\n");
}
为了实现能够玩完一局游戏后能再次选择是否继续游戏,所以采用循环结构。同时要想当程序开始执行时就能打印菜单,因此采用do while循环。其代码实现如下:
#include <stdio.h>
void menu()
{
printf("******************************\n");
printf("****** 1. PLAY ******\n");
printf("****** 2. EXIT ******\n");
printf("******************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入数字1/0>:");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 0:
break;
}
} while (input);
return 0;
}
程序执行后图1所示:
由图一可以看出当我们输入1时,代表开始游戏(由于没有游戏的实现代码,所以会再次回到打印菜单并输入1或者0,直到输入0程序才会结束)?:
?接下来就是完成游戏的实现逻辑(其代码存放在game.c中):
因为选1时开始游戏,所以game()放在case 1后
? ? ?要想玩游戏首先得有一个空棋盘,即在屏幕上打印一个空棋盘。虽然棋盘在屏幕上看起来是是个3X3的表格,但可以通过一个含有3X3的二维数组来实现。为了将数组中的每个元素初始化为空字符(即‘ ’),所以定义一个名为InitBoard的函数。由于该函数是用来初始化数组的,故将数组、三子棋的行数、列数作为参数传给InitBoard函数。为了方便以后将代码改为五子棋等,将函数参数中的char board[3][3]改为char board[ROW][COL],其中ROW和COL是在game.h中定义的常量,这样以后要更改棋盘的大小就可以通过更改ROW和COL来实现,而不是对每个board中的行和列进行修改。
?
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for ( i = 0; i <row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] =' ';
}
}
}
初始化棋盘后就需要对棋盘进行打印,创建一个名为DisplayBoard的函数。参考下图的空棋盘可以看出,该空棋盘分为三个部分,第一、三、五行是“? %c | %c | %c ”(为了美观,每个%c即字符都与两边的‘|’之间有空格),第二、四行是“---|---|---”。而第一三五行又可以看成‘?%c ’?+‘|’+‘?%c ’+‘|’+......,其中“ %c ”的个数为棋盘的列数(即为col),而‘|’的个数为列数减1(即为col-1)。第二四行同理可分为‘---’ + ‘|’ + ‘---’ +.......。
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[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");
}
}
打印的空棋盘如下图所示:?
?
打印完棋盘后就是玩家和电脑进行下棋,我设计的是由玩家先下,所以先定义一个名为Player_move的函数来实现玩家输入,同时玩家输入后又要再次打印棋盘,即再次执行DisplayBoard函数。
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
Player_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
Computer_move(board, ROW, COL);
}
void Player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while(1)
{
printf("请玩家输入数字>;");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
if (board[x - 1][y - 1] != ' ')
{
printf("该位已被占用,请重新输入!");
}
}
else
printf("输入错误,请重新输入!");
}
该函数要满足以下几点:1只能输入1~3的整数,如果不属于1~3时,应该会收到提醒输入错误,并重新输入;2例如输入1,1时,棋盘上对应的点应该是对应board[0[0]元素的位置,即输入x y时应该对应arr[x-1][y-1];3,玩家想要输入的位置上应该为空,不能重复输入。例如输入1 1时,屏幕上打印的棋盘为?:
?
玩家输入并再次打印棋盘后就轮到电脑下棋,电脑下棋的位置应该满足随机性,所以使用rand函数?,在使用rand前要使用srand。同时电脑下棋的位置也必须为空,否则重新选取位置。电脑完成下棋这一步骤后再次打印棋盘。
void Computer_move(char board[ROW][COL], int row, int col)
{
//int x = rand() % ROW;
//int y = rand() % COL;
printf("电脑回合>;\n");
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
? ? ? 当玩家和电脑都能完成下棋这一动作时就需要对其最终结果进行判断,即玩家获胜、电脑获胜、以及平局,定义一个is_win()函数用于判断这三种情况。获胜的条件是某一行或者某一列亦或者对角线上有三个相同的字符,但是要注意这三个字符一定不能为空字符。平局的条件是棋盘被填满,定义一个is_full函数用于判断棋盘是否被填满。代码如下:
int is_full(char board[ROW][COL], int row, int col)//用于判断棋盘是否已经被填满,即平局
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return '0';
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)//用于判断获胜和平局
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]&& board[i][2]!=' ')
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i]&& board[2][i]!=' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&& board[2][2]!=' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]&& board[2][0]!=' ')
{
return board[0][2];
}
if (1 == is_full(board, row, col))
return 'Q';
else
return 'c';
}
?当is_win函数返回‘O’时代表玩家获胜;返回‘X’时,电脑获胜。返回‘C’表示继续轮到玩家或者电脑下棋,即棋盘还有空余其无人获胜;返回‘Q’时表示平局。
? 最终game.h、game.c、test.c中的代码如下:
******************************************game.h*****************************************
# pragma once
#define ROW 3
#define COL 3
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void Player_move(char board[ROW][COL], int row, int col);
void Computer_move(char board[ROW][COL], int row, int col);
char is_win(char board[ROW][COL], int row, int col);
******************************************game.c*****************************************
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for ( i = 0; i <row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] =' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[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_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while(1)
{
printf("请玩家输入数字>;");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'O';
break;
}
if (board[x - 1][y - 1] != ' ')
{
printf("该位已被占用,请重新输入!");
}
}
else
printf("输入错误,请重新输入!");
}
}
void Computer_move(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] = 'X';
break;
}
}
}
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return '0';
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]&& board[i][2]!=' ')
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i]&& board[2][i]!=' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2]&& board[2][2]!=' ')
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0]&& board[2][0]!=' ')
{
return board[0][2];
}
if (1 == is_full(board, row, col))
return 'Q';
else
return 'c';
}
******************************************test.c***************************************** 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 board[ROW][COL] = {0};
InitBoard( board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
char ret = 'a';
while (1)
{
Player_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'c')
{
break;
}
Computer_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'c')
{
break;
}
}
if (ret == 'O')
printf("玩家获胜!\n");
else if (ret == 'X')
printf("电脑获胜!\n");
else
printf("平局\n");
break;
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入数字1/0>:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("三子棋游戏开始!\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
return 0;
}
?
?
?
?
?
?
|