一、实现的核心。
1.菜单功能的提示
void menu()
{
printf("****************************\n");
printf("****** 1.play 0.exit ******\n");
printf("****************************\n");
}
2.测试是否能够进行选择进入
void test()
{
int input = 0;
printf("请选择是否进入游戏:\n");
do
{
scanf("%d", &input);
switch (input)
{
case 0:
printf("游戏退出:\n");
break;
case 1:
game();
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
}
3.将定义的数组初始化为空格。
void Tnit_Board(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] = ' ';
}
printf("\n");
}
}
4.棋盘格的展示
这里需要将数组插入到棋盘格,方便后续对战中,能够及时更新棋子的情况。
void Display_Board(char board[ROW][COL], int row, int col) //显示棋盘
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)
{
printf("---");
printf("|");
}
printf("\n");
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //传递参数的时候传递的是具体的值,ROW COL导致错误
printf("|");
}
printf("\n");
for (j = 0; j < col; j++)
{
printf("---");
printf("|");
}
printf("\n");
}
}
5.玩家走棋子的时候要注意重新定义两个变量,方便后续输入,同时为了方便玩家使用,我们将数组的下标统一加一,玩家在棋盘格的规定区域内可以用星号填充,这里后续判断输赢的时候会用到。
void Player_Move(char board[ROW][COL], int row, int col) //玩家走
{
int x, y;
while (1)
{ printf("请输入要走的坐标\n");
scanf("%d %d", &x, &y);
if (x > 0 && x < row+1 && y>0 && y < col+1) //实际坐标是0-2
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置被有棋子\n");
}
}
else
{
printf("输入错误请重新输入:\n");
}
}
}
6.这里主要是让电脑通过产生随机数的方式,实现下棋,这里产生的数字加了一,所以电脑的下标就不用在考虑了。
void Computer_Move(char board[ROW][COL], int row, int col) //电脑走
{
int x, y;
while (1)
{
x = rand() % ROW + 1;
y = rand() % COL + 1; //产生1---ROW的数
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
else
{
continue;
}
}
}
7.这里就是判断输赢的情况,主要是行,列,以及左右对角线,这里要实现N子棋的话,需要改变一下判断输赢的条件,后续我会更新上来。最后面那个循环是判断是否还有空位置,如果有,就继续落子,如果没有,就产生平局,因为如果有输赢的话,前面的if已经判断完成了。
char IsWin(char board[ROW][COL], int row, int col) //判断输赢
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0]; //判断行相等
break;
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
break; //判断列相等
}
}
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ') //判断对角线
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
for (i = 0; i < row; i++) //判断是否还有空位,平局的情况
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
8.这里就是一个游戏流程的问题,首先定义数组,然后初始化,然后展示出棋盘,通过玩家的输入,进入循环,首先是玩家落子,然后更新棋盘,然后电脑落子,然后更新,直到通过返回值,判断出输赢或者平局。最后在输出一个菜单,再次选择一下,要不要继续玩,
void game()
{
char board[ROW][COL] = { 0 };
Tnit_Board(board, ROW, COL); //初始化棋盘
Display_Board(board, ROW, COL);//打印棋盘
while (1)
{
printf("玩家回合:\n");
Player_Move(board, ROW, COL);
Display_Board(board, ROW, COL);//打印棋盘
printf("电脑回合:\n");
Computer_Move(board, ROW, COL);
Display_Board(board, ROW, COL);//打印棋盘
int ret = IsWin(board, ROW, COL);
if (ret == 1)
{
printf("平局结束\n");
break;
}
if (ret == '*')
{
printf("玩家胜利\n");
break;
}
if (ret == '#')
{
printf("电脑胜利\n");
break;
}
//返回0的时候会继续下棋
}
menu();
}
二、函数的具体信息
1. game.h,头文件的内容
头文件里定义了宏,方便后续改变棋盘的大小,以及对后续使用的函数的声明。
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3 //定义棋盘长度
#define COL 3 //定义棋盘宽度
#define CHESS_NUM 3 //定义棋子个数
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu(); //菜单
void test(); //功能选择
void game(); //游戏开始
void Tnit_Board(char board[ROW][COL], int row, int col); //初始化数组
void Display_Board(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 IsWin(char board[ROW][COL], int row, int col); //判断输赢
2.game.c的内容
需要注意的是这里需要引头文件。
#include"game.h"
void menu()
{
printf("****************************\n");
printf("****** 1.play 0.exit ******\n");
printf("****************************\n");
}
void test()
{
int input = 0;
printf("请选择是否进入游戏:\n");
do
{
scanf("%d", &input);
switch (input)
{
case 0:
printf("游戏退出:\n");
break;
case 1:
game();
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
}
void Tnit_Board(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] = ' ';
}
printf("\n");
}
}
void Display_Board(char board[ROW][COL], int row, int col) //显示棋盘
{
int i = 0;
int j = 0;
for (j = 0; j < row; j++)
{
printf("---");
printf("|");
}
printf("\n");
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]); //传递参数的时候传递的是具体的值,ROW COL导致错误
printf("|");
}
printf("\n");
for (j = 0; j < col; j++)
{
printf("---");
printf("|");
}
printf("\n");
}
}
void Player_Move(char board[ROW][COL], int row, int col) //玩家走
{
int x, y;
while (1)
{ printf("请输入要走的坐标\n");
scanf("%d %d", &x, &y);
if (x > 0 && x < row+1 && y>0 && y < col+1) //实际坐标是0-2
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置被有棋子\n");
}
}
else
{
printf("输入错误请重新输入:\n");
}
}
}
void Computer_Move(char board[ROW][COL], int row, int col) //电脑走
{
int x, y;
while (1)
{
x = rand() % ROW + 1;
y = rand() % COL + 1; //产生1---ROW的数
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
else
{
continue;
}
}
}
char IsWin(char board[ROW][COL], int row, int col) //判断输赢
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0]; //判断行相等
break;
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
break; //判断列相等
}
}
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ') //判断对角线
{
return board[0][0];
}
if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != ' ')
{
return board[0][2];
}
for (i = 0; i < row; i++) //判断是否还有空位,平局的情况
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
void game()
{
char board[ROW][COL] = { 0 };
Tnit_Board(board, ROW, COL); //初始化棋盘
Display_Board(board, ROW, COL);//打印棋盘
while (1)
{
printf("玩家回合:\n");
Player_Move(board, ROW, COL);
Display_Board(board, ROW, COL);//打印棋盘
printf("电脑回合:\n");
Computer_Move(board, ROW, COL);
Display_Board(board, ROW, COL);//打印棋盘
int ret = IsWin(board, ROW, COL);
if (ret == 1)
{
printf("平局结束\n");
break;
}
if (ret == '*')
{
printf("玩家胜利\n");
break;
}
if (ret == '#')
{
printf("电脑胜利\n");
break;
}
//返回0的时候会继续下棋
}
menu();
}
3.主函数的代码
#include "game.h"
int main()
{
srand((int)time(NULL));
menu();
test();
system("pause");
return 0;
}
实现结果:
心得体会:将程序分模块实现,需要注意头文件的引入,在函数实现的时候一定要注意细节,实现一步,在进行下一步,写好之后要进行测试,优化步骤,我写的时候有时候漏掉了函数类型,在返回值的时候,将单引号打成双引号,导致落子显示的标志不对,通过这个游戏的训练,我对自定义函数的使用更加熟练,同时对while do while 循环理解更加深刻,之前每次实现选择功能的时候,把输入函数放在循环外面,导致输入一次就没了。
这个程序存在一个小的BUG,电脑可能会落子到重复的地方,导致程序卡住,我测试 半天也没改好,后续会优化成N子棋。