目录
?前言
游戏所要实现的功能
实现三子棋游戏
完整代码
? 总结
?前言
三子棋也叫井字棋,这个游戏很多人都玩过,游戏规则我就不用过多的叙述了。接下来我们来看一下,使用C语言具体怎样实现这个游戏。
这个游戏使用C语言中循环、数组、函数的知识点来实现。因为这个游戏写的代码相对比较多一些,这里使用多个文件分模块来完成这个游戏。
多文件中每个文件具体写什么内容在下面这篇文章中已经分享过了这里就不重复叙述了,感兴趣的朋友可以看一下。
C语言中的函数
实现这个游戏需要使用三个文件:
game.h :该文件实现宏定义,库函数的引用,自定义函数的声明
game.c :该文件实现每个函数具体实现的功能
main.c :该文件实现每个函数的调用
游戏所要实现的功能
- 使用字符 '*' 表示玩家(1)下的棋
- 使用字符 '#' 表使电脑下的棋 或 玩家(2)下的棋
1、打印菜单
菜单的打印在下面这篇文章中提到过这里就不详细叙述了,感兴趣的朋友可以看一下。
C语言实现猜数字游戏
2、创建棋盘
- 对棋盘赋值,因为棋盘中放置的是字符,所以将棋盘初始化为空格字符(' ')。
- 打印棋盘,三子棋总共有9个格子,这里使用字符 ' - ' 与字符 ' | ' 划分棋盘中的格子
3、实现下棋功能
- 玩家下棋
- 电脑下棋
4、对弈结局
- 玩家赢
- 电脑赢 或 玩家2赢
- 未结束,继续
- 平局
实现三子棋游戏
1、打印菜单
#include<stdio.h>
//生成菜单函数
void menu()
{
printf("****************************************\n");
printf("**** 1.Play chess with a computer ****\n");
printf("**** 2.Play chess with the palyer ****\n");
printf("**** 0.exit ****\n");
printf("****************************************\n");
}
void test()
{
int input = 0;
do {
//菜单
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:printf("与电脑对弈\n");
break;
case 2:printf("与玩家对弈\n");
break;
case 0:printf("退出游戏\n");
break;
default:printf("选择错误\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
测试结果
2、创建棋盘(使用二维数组)。
创建棋盘的时候考虑到可以能会修改棋盘的大小,这里使用宏定义来确定二维数组的行数和列数。
//ROW:行 ;COL:列
#define ROW 3
#define COL 3
对数组传参可以直接使用宏定义(ROW,COL),如果想修改棋盘的大小,只需要修改宏定义中参数的大小。
void game1()
{
//将数据存储到一个字符二维数组中,玩家1下棋:'*',电脑下棋:'#'
char board[ROW][COL] = { 0 };
InitBoard(board, ROW,COL);//初始化棋盘
}
void game2()
{
//将数据存储到一个字符二维数组中,玩家1下棋:'*',玩家2下棋:'#'
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);//初始化棋盘
}
(1)将棋盘初始化为空格
//对棋盘初始化函数的实现
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] = ' ';
}
}
}
(2)打印棋盘
先写一个简单的棋盘打印,帮助大家理解。
//对棋盘打印功能的实现
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
//数据
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
//分割行
if (i < row - 1)
{
printf("---|---|---\n");
}
}
}
这样写可以打印出棋盘,但是这种写法会将棋盘的列写死。如果想要将棋盘修改为10*10的,这种写法是实现不了的。
打印棋盘代码修改
//对棋盘打印功能的实现
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");
}
}
测试结果
?3、实现下棋
(1)玩家下棋
//对玩家下棋功能的实现
void player_Move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋,请输入坐标:>");
while (1)
{
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;
}
else
{
printf("该位置已有棋子,请重新输入!\n 请输入:>");
}
}
else
{
printf("您输入的坐标非法,请重新输入!\n 请输入:>");
}
}
}
测试结果
(2)电脑下棋
电脑下棋使用随机数,获取棋盘坐标。
C语言中随机数的生成在下面这篇文章中详细的叙述了,感兴趣的朋友可以看一下。
C语言实现猜数字游戏
//对电脑下棋功能的实现
void computer_Move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋 :>\n");
while (1)
{
x = rand() % row; //0~2
y = rand() % col; //0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
测试结果
(3) 玩家2下棋与玩家下棋的实现功能一样
?4、判断结局
- 玩家赢 -- 返回 '*'
- 电脑赢 OR 玩家2赢 -- 返回 '#'
- 平局 -- 返回 'Q'
- 继续 -- 返回 'C'
char ret = 0;
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 == '*')
{
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
实现对棋局结果的判断
//实现棋局结果
char is_win(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][2] != ' ')
{
return board[i][0];
}
}
//判断列
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
{
return board[0][j];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
{
return board[1][1];
}
//判断平局
if (1==is_full(board, row, col))
{
return 'Q';
}
//判断继续
return 'C';
}
?
完整代码
game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//ROW:行 ;COL:列
#define ROW 3
#define COL 3
//使用小写 row,col接收数组大小的参数
//棋盘初始化函数声明
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);
//玩家2下棋
void player_Move2(char board[ROW][COL], int row, int col);
//判断输赢
//玩家赢 --返回 '*'
//电脑赢OR玩家2赢 --返回 '#'
//平局 -- 返回 'Q'
//继续 -- 返回 'C'
char is_win(char board[ROW][COL], int row, int col);
game.c
#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++)
// {
// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
// if (i < row - 1)
// {
// printf("---|---|---\n");
// }
// }
//}
//对棋盘打印功能的实现 - 方法(二)
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;
printf("玩家下棋,请输入坐标:>");
while (1)
{
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;
}
else
{
printf("该位置已有棋子,请重新输入!\n 请输入:>");
}
}
else
{
printf("您输入的坐标非法,请重新输入!\n 请输入:>");
}
}
}
//对电脑下棋功能的实现
void computer_Move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋 :>\n");
while (1)
{
x = rand() % row; //0~2
y = rand() % col; //0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//对玩家2下棋功能的实现
void player_Move2(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家2下棋,请输入坐标:>");
while (1)
{
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;
}
else
{
printf("该位置已有棋子,请重新输入!\n 请输入:>");
}
}
else
{
printf("您输入的坐标非法,请重新输入!\n 请输入:>");
}
}
}
//判断棋盘是否满了
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;
int j = 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 (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ')
{
return board[0][j];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
{
return board[1][1];
}
//判断平局
if (1==is_full(board, row, col))
{
return 'Q';
}
//判断继续
return 'C';
}
main.c
//调用game.h文件
#include"game.h"
//生成菜单函数
void menu()
{
printf("****************************************\n");
printf("**** 1.Play chess with a computer ****\n");
printf("**** 2.Play chess with the palyer ****\n");
printf("**** 0.exit ****\n");
printf("****************************************\n");
}
void game1()
{
//将数据存储到一个字符二维数组中,玩家1下棋:'*',电脑下棋:'#'
char board[ROW][COL] = { 0 };
InitBoard(board, ROW,COL);//初始化棋盘
//DisplayBoard(board, ROW, COL);//打印棋盘
//下棋
char ret = 0;
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 == '*')
{
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
}
void game2()
{
//将数据存储到一个字符二维数组中,玩家1下棋:'*',玩家2下棋:'#'
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);//初始化棋盘
//DisplayBoard(board, ROW, COL);//打印棋盘
char ret = 0;
while (1)
{
player_Move(board, ROW, COL);//玩家1下棋
DisplayBoard(board, ROW, COL);//打印棋盘
char ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
player_Move2(board, ROW, COL);//玩家2下棋
DisplayBoard(board, ROW, COL);//打印棋盘
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("玩家2赢了\n");
}
else
{
printf("平局\n");
}
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
//菜单
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:game1();
break;
case 2:game2();
break;
case 0:printf("退出游戏\n");
break;
default:printf("选择错误,请重新选择!\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
代码虽然可以实现三子棋,但是存在着许多需要优化的地方。
比如:在对结局判断的时候直接将落子的位置写死了。可以优化一下,将落子的位置使用变量表示。
由于本人目前水平有限只能写成这样,后期对C语言的知识掌握的更丰富了,还会继续优化三子棋游戏。
? 总结
使用C语言实现三子棋是对C语言中循环语句、选择语句、数组、函数知识点的灵活使用。通过写这个游戏,也发现了自己还有很多知识没有掌握,还要继续学习更多的知识。
任何知识的学习都是需要反复练习、反复应用,这样才能将所学的知识掌握。
?
|