前言
实现一个简易的三子棋游戏,玩家能够和电脑进行对战,分出高下。
一、整体流程
- 创建三个文件,test.c用来放测试三子棋功能,game.c里放置游戏各个功能的实现代码,game.h用来放置需要用到的所有头文件及函数的声明。
- 在test.c中写一个菜单打印函数,用来每次游戏时打印菜单。在主函数中实现选择进入游戏,退出游戏等功能。当选择进入游戏,游戏具体操作的代码放在一个game()函数中。
- 书写game()函数,创建一个棋盘,并且完成棋盘的初始化,打印棋盘,玩家下棋,电脑下棋,判断输赢等功能。将这些功能包装成函数放在game.c中,并在game.h中声明。
- 完善代码并测试功能,进行修改完善。
二、具体代码实现
1、制作游戏菜单
void menu()
{
printf("************************\n");
printf("******1 开始游戏 *******\n");
printf("******0 退出游戏 *******\n");
printf("************************\n");
}
2、制作出主函数框架
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//这里是后面电脑下棋需要用到的
do {
menu();
printf("请输入你的选择>\n");
scanf("%d", &input);//输入选择
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入非法,请重新输入\n");
break;
}
} while (input);
return 0;
}
3、接下来完善game()函数,将游戏各个功能写在game.c中。用二维数组放置棋盘,棋盘的行和列长度可以放在头文件中定义,方便整体的修改。
void game()
{
char board[ROW][COL] = { 0 };//棋盘
InitBoard(board, ROW, COL);//置空初始化棋盘
DisplayBoard(board, ROW, COL);//打印棋盘
char ret = ' ';
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'B')
{
break;
}
printf("---------------------\n");
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'B')
{
break;
}
}
代码中的一些属性会在后续具体函数的代码中出现
4、棋盘中的元素都为0,需要进行初始化
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';//将数组中所有元素置为空格
}
}
}
5、将棋盘打印出来,加上一些线区分每个棋子位置
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
6、实现玩家下棋的功能
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("该你下了(以空格隔开):\n");
scanf("%d %d", &x, &y);//输入想要下的坐标(从1开始)
if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标是否合法
{
if (board[x - 1][y - 1] == ' ')//判断输入坐标是否已有棋子
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标以被占用,请重新输入:\n");
}
}
else
{
printf("输入非法,请重新输入:\n");
}
}
}
7、实现电脑下棋功能
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("轮到电脑了:\n");
while (1)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
~srand((unsigned int)time(NULL));已经在主函数中写上,利用时间戳返回一个随机数
~int x = rand() % row ;可以得到0 ~ row-1的随机数,整体加一便可得到1~row的随机数
~对col也是一样
8、判断是否胜利
这里需要用到一个判断棋盘是否已满的函数
int IsFull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
//如果一个空格都没有,走出了循环,说明已经满了
return 1;
}
判断是否胜利,返回不同的字符,在game()函数中进行判断,得出谁获得胜利
该判断只适用于3*3棋盘的三子棋
char IsWin(char board[ROW][COL], int row, int col)
{
//行
for (int 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];
}
}
//列
for (int i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局
if (IsFull(board, row, col))
{
return 'A';
}
return 'B';
}
9、记得将需要的头文件函数等在game.h中进行声明,并在test.c中引用该头文件
以下是头文件中的内容
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
int IsFull(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
三、整体代码
game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
int IsFull(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
game.c
#include "game.h"
//数组置空
void InitBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印数组
void DisplayBoard(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
for (int j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("该你下了(以空格隔开):\n");
scanf("%d %d", &x, &y);//输入想要下的坐标(从1开始)
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标以被占用,请重新输入:\n");
}
}
else
{
printf("输入非法,请重新输入:\n");
}
}
}
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("轮到电脑了:\n");
while (1)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判断是否满了
int IsFull(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
//判断是否胜利
char IsWin(char board[ROW][COL], int row, int col)
{
//行
for (int 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];
}
}
//列
for (int i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局
if (IsFull(board, row, col))
{
return 'A';
}
return 'B';
}
test.c
#include "game.h"
//游戏菜单
void menu()
{
printf("************************\n");
printf("******1 开始游戏 *******\n");
printf("******0 退出游戏 *******\n");
printf("************************\n");
}
//三子棋游戏
void game()
{
char board[ROW][COL] = { 0 };//棋盘
InitBoard(board, ROW, COL);//置空
DisplayBoard(board, ROW, COL);//打印棋盘
char ret = ' ';
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'B')
{
break;
}
printf("---------------------\n");
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'B')
{
break;
}
}
if (ret == '*')
{
printf("恭喜你取得胜利\n");
}
else if (ret == '#')
{
printf("很遗憾,你输了\n");
}
else
{
printf("你与电脑势均力敌\n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请输入你的选择>\n");
scanf("%d", &input);//输入选择
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入非法,请重新输入\n");
break;
}
} while (input);
return 0;
}