今天小杜为大家带来一个C语言小游戏——三子棋
在我们学习编程语言的过程中,需要有这样有趣的项目来保持自己对于编程的兴趣和信心。
1.游戏整体思路
我们需要有三个文件:
- test.c —— 测试游戏
- game.h —— 游戏函数的声明
- game.c —— 游戏函数的实现
2.游戏菜单的创建
进入游戏时,首先出现的是菜单界面
我们定义一个“菜单函数”menu( )来实现这一功能
游戏菜单应该实现这几个功能:
- 游戏的进入
- 游戏的退出
- 非法输入的返回提示和说明
接下来是我们实现这一功能的代码块
#include<stdio.h> #include"game.h" void menu() { printf("********************\n"); printf("****** 1.play ******\n"); printf("****** 0.exit ******\n"); printf("********************\n"); } int main() { int input = 0; do { menu(); printf("请输入:>"); scanf("%d", &input); switch (input) { case 1: printf("三子棋\n"); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误\n"); break; } } while (input); return 0; }
这是该模块菜单函数的运行截图
3.游戏主体的实现
3.1棋盘的初始化
游戏刚开始时,我们需要对棋盘进行初始化操作,对棋盘进行清空,以保证后续游戏的正常进行。我们定义一个InitBoard()函数来进行棋盘的初始化操作
代码如下
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] = ' '; } } }
3.2打印棋盘
初始化棋盘后就需要打印棋盘了
打印棋盘的代码如下
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.3玩家下棋
打印好棋盘,就要进行我们的下棋阶段
我们规定玩家先下棋
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] != ' ') { printf("该位置已被占用,请输入其他坐标\n"); } else { board[x - 1][y - 1] = '*'; break; } } else { printf("输入非法,请重新输入\n"); } } }
玩家输入对应的合法坐标下棋,接下来就是电脑下棋
暂且不设计电脑对抗玩家的算法,就让电脑产生一个棋盘内部的随机坐标
3.4电脑下棋
void ComputerBoard(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("电脑下棋\n"); while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
给电脑设计了随机数rand()函数,但这个函数需要srand()设置,所以我们在main()函数开头加上srand()
接下来写一个判断输赢的函数来进行判断
3.5判断输赢
三子棋游戏出现的结果有以下四种,我们用各自对应的符号进行判断
//玩家赢 - *
//电脑赢 - #
//平局 - Q
//继续游戏 - C
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]; } } 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 (IsFull(board, row, col)) return 'Q'; return 'C'; }
3.6棋盘满
接下来我们还需要有一个函数来判断棋盘是否已满
static int IsFull(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; }
我们用static修饰这个函数,使当前函数只能在本文件内部使用
3.7game()函数
上面我们铺垫了所有三子棋所要用到的函数,这些函数在game()函数中使用
void game() { char ret = 0; char board[ROW][COL] = {0}; InitBoard(board,ROW,COL); DisplayBoard(board,ROW,COL); while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') break; //电脑下棋 ComputerBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') { printf("玩家赢\n"); } if (ret == '#') { printf("电脑赢\n"); } if (ret == 'Q') { printf("平局\n"); } }
4.整体代码
这些代码我们在实际使用时是需要封装在不同的文件内的
所以我们定义了test.c,game.c,game.h文件封装我们所有用到的函数以及头文件
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] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') break; //电脑下棋 ComputerBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断输赢 ret = IsWin(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') { printf("玩家赢\n"); } if (ret == '#') { printf("电脑赢\n"); } if (ret == 'Q') { printf("平局\n"); } } int main() { int input = 0; do { menu(); printf("请输入:>"); scanf("%d", &input); switch (input) { case 1: printf("三子棋\n"); game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误\n"); break; } } while (input); return 0; }
game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #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 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] != ' ') { printf("该位置已被占用,请输入其他坐标\n"); } else { board[x - 1][y - 1] = '*'; break; } } else { printf("输入非法,请重新输入\n"); } } } void ComputerBoard(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("电脑下棋\n"); while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } static int IsFull(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 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]; } } 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 (IsFull(board, row, col)) return 'Q'; return '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 PlayerMove(char board[ROW][COL], int row, int col); //电脑下棋 void ComputerBoard(char board[ROW][COL], int row, int col); //判断输赢 //有四种可能 //玩家赢 - * //电脑赢 - # //平局 - Q //继续游戏 - C char IsWin(char board[ROW][COL], int row, int col);
我们把所有的函数声明和头文件以及宏定义都放在我们自己创建的game.h文件中
我们在其他文件中使用时只需要包含该文件用双引号引住即可
5.结束
今天我们练习写出来自己的三子棋游戏,这是一个很好的进步
小杜跟各位小伙伴在一起成长,祝我们都能成为大牛!
//小杜的成长之路