“纵有疾风来,人生不言弃,风乍起,合当奋意向此生。” 今天我们一起来学习一下三子棋小游戏用C语言怎么写出来?
三子棋小游戏
- 1.游戏规则介绍
- 2.游戏准备
- 3.游戏的实现
- 3.1生成菜单
- 3.2游戏的具体实现
- 3.2.1初始化棋盘
- 3.2.2打印棋盘
- 3.2.3玩家下棋(玩家下棋为O)
- 3.2.4电脑下棋(电脑下棋为X)
- 3.2.5判断输赢
- 3.2.6棋盘的优化
- 4.三子棋游戏完整的代码实现(详细源码)
1.游戏规则介绍
《三子棋》是一款古老的民间传统游戏,又被称为黑白棋、圈圈叉叉棋、井字棋、一条龙、九宫棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子连成一条线的一方则视为胜利者。
2.游戏准备
这里呢,我们需要准备三个源文件,分别是test.c game.c game.h
(名称随意,尽量通俗易通一些比较好)可能有疑问了,这里为什么需要三个源文件呢?会不会显得很麻烦?在前面的学习中,我们也提到了未来在工程中代码比较多,函数一般放在.h文件
中声明,在.c文件
中实现。
分文件书写形式的优点:1.方便多人协作 2.保护代码
这里我们给大家介绍一下在三子棋这个游戏里面,每个文件是做什么的呢?
(1)头文件game.h
,头文件里是用来存放函数的声明,#define常量的定义,库函数的引用的。
(2)源文件test.c
,这个文件里面放的是游戏的测试逻辑。
(3)源文件game.c
,这个文件里面放的是游戏的实现逻辑(函数实现)。
3.游戏的实现
3.1生成菜单
这里呢,我们通过switch语句
给用户选择,当用户输入不同的数字,我们的程序就会给出不同的功能。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void menu()//生成菜单的函数
{printf("******************************\n");printf("********** 1.play **********\n");printf("********** 0.exit **********\n");printf("******************************\n");
}
void game()//实现玩游戏的函数
{}
int main()
{int input = 0;//用户选择do//利用循环可以便于用户进行多次游戏{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏!\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;
}
通过上面的代码,我们已经构建出了基本的框架:
3.2游戏的具体实现
我们发现,在上面的框架代码中缺少了游戏实现部分的代码,这里,我们在慢慢的一点点细化游戏过程。
首先,我们可以看到,我们需要先构造出一个3*3的棋盘。使得每个九个空位都处于空的状态。这里我们就想到了二维数组的概念,那我们一起来试试吧!
3.2.1初始化棋盘
//game.h
#pragma once
# define ROW 3
# define COL 3
//初始化棋盘的函数的声明
void InitBoard(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] = ' ';}}
}//test.c
void game()
{//最开始的时候数组的内容全是空格char board[ROW][COL]; InitBoard(board, ROW, COL);
}
3.2.2打印棋盘
初始化棋盘之后,我们需要将棋盘打印出来才能被用户看到,那么我们同样的可以利用for循环
来完成这步操作。
//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);//game.c
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]);}printf("\n");}
}//test.c
DisplayBoard(board, ROW, COL);
但是我们发现,这里留下了一大片空白,根本看不到棋盘,这是为什么呢?因为我们已经将棋盘初始化为空格了,显然我们是看不到的,而我们想要的是九宫格的样子,这里的话我们就可以用-和|
来组成我们的棋盘了。
//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);//game.c
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]);printf("---|---|---\n");}
}//test.c
DisplayBoard(board, ROW, COL);
但是,我们发现,这个棋盘还是存在不足,它的下面多了一条线,那么我们就需要调整一下for循环的循环语句了。
这里,我们给出修改后的代码及运行结果:
//game.h
//打印棋盘的函数声明
void DisplayBoard(char board[ROW][COL], int row, int col);//game.c
void DisplayBoard(char board[ROW][COL], int row, int col)//打印棋盘函数的实现
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){int j = 0;for (j = 0; j < col; j++){printf("---");//再打印分隔行if (j < col - 1){printf("|");}} }printf("\n");}
}//test.c
DisplayBoard(board, ROW, COL);
这样的话,我们通过修改# define ROW 3 # define COL 3
的值来改变棋盘的大小:
3.2.3玩家下棋(玩家下棋为O)
//game.h
//玩家下棋函数声明
void PlayerMove(char board[ROW][COL], int row, int col);//game.c
//玩家下棋函数的实现
void PlayerMove(char board[ROW][COL], int row, int col)
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("请输入坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' ')//玩家并不会考虑到数组下标从0开始,这里我们需要考虑进去{board[x - 1][y - 1] = 'O';break;}else{printf("该坐标已被占用,请重新下棋!\n");}}else{printf("坐标非法,请重新输入!\n");}}
}//test.c
while (1){PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来}
3.2.4电脑下棋(电脑下棋为X)
//game.h
//电脑下棋函数声明
void ComputerMove(char board[ROW][COL], int row, int col);//game.c
//电脑下棋函数的实现
//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % row;//电脑随机产生坐标y = rand() % col;if (board[x][y] == ' '){board[x][y] = 'X';break;}}
}//test.c
while (1){ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来}
但是,我们这里目前只考虑让这个游戏玩起来,电脑下棋只是随机产生一些值,并没有任何的逻辑在里面。
3.2.5判断输赢
输赢情况有以下几种:
1.玩家赢-返回O
2.电脑赢-返回X
3.平局-返回Q
4.游戏继续-返回C
//game.h
//判断输赢函数声明
char Is_win(char board[ROW][COL], int row, int col);//game.c
//判断棋盘是不是满了的函数
static 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][0] != ' '){return board[i][0];}}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];}}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 (Is_full(board, row, col)){return 'Q';}return 'C';
}//test.c
if (ret == 'O'){printf("玩家赢!\n");}else if (ret == 'X'){printf("电脑赢!\n");}else{printf("平局!\n");}
3.2.6棋盘的优化
我们发现程序基本已经可以运行了,但是如果添加清屏的操作会不会更好呢?这里,我们可以完善一下。
这里我们就需要引入system("cls")
,它就可以实现清屏的操作啦!
4.三子棋游戏完整的代码实现(详细源码)
game.h文件
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.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);
//判断输赢函数声明
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;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){int j = 0;for (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;printf("玩家下棋\n");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;}else{printf("该坐标已被占用,请重新下棋!\n");}}else{printf("坐标非法,请重新输入!\n");}}
}
//电脑下棋函数的实现
//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");int x = 0;int y = 0;while (1){x = rand() % row;//电脑随机产生坐标y = rand() % col;if (board[x][y] == ' '){board[x][y] = 'X';break;}}
}
//判断棋盘是不是满了的函数
static 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][0] != ' '){return board[i][0];}}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];}}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 (Is_full(board, row, col)){return 'Q';}return 'C';
}
test.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"
//创建菜单
void menu()
{printf("******************************\n");printf("********** 1.play **********\n");printf("********** 0.exit **********\n");printf("******************************\n");
}
void game()
{char ret = 0;//最开始的时候数组的内容全是空格char board[ROW][COL]; InitBoard(board, ROW, COL);DisplayBoard(board, ROW, COL);while (1){PlayerMove(board, ROW, COL);//玩家下棋函数调用DisplayBoard(board, ROW, COL);//将玩家下棋结果打印出来//判断输赢ret = Is_win(board, ROW, COL);if (ret != 'C'){break;}system("cls");//清屏DisplayBoard(board, ROW, COL);ComputerMove(board, ROW, COL);//电脑下棋函数调用DisplayBoard(board, ROW, COL);//将电脑下棋结果打印出来ret = Is_win(board, ROW, COL);if (ret != 'C'){break;} system("cls");//清屏DisplayBoard(board, ROW, COL);}system("cls");//清屏DisplayBoard(board, ROW, COL);if (ret == 'O'){printf("玩家赢!\n");}else if (ret == 'X'){printf("电脑赢!\n");}else{printf("平局!\n");}}
int main()
{int input = 0;srand((unsigned int)time(NULL));do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏!\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;}
以上就是关于三子棋游戏的全部代码啦!当然这个程序还是存在可优化的空间(比如电脑下棋的时候能不能更加智能一点,还有待思考),欢迎大家在评论区交流。