天天看点

三子棋——年轻人的第一款小游戏前言正文总结 

目录

前言

正文

主函数部分(test.c)

头文件部分(game.h)

功能实现函数部分(game.c)

 1.初始化函数

2.打印棋盘函数

3.玩家移动函数

4.电脑移动函数

5.判断输赢函数

6.重回game函数

效果展示

总结 

前言

  经过一段时间的学习,分支与循环、数组与函数的相关知识已经足够支撑我们完成一个小游戏了,这个小游戏不需要太多的功能,也不需要太复杂的逻辑,只需要懂点循环与分支,懂点数组的使用以及函数如何传参和返值即可。作为草稿纸上常出现的小游戏,三子棋的逻辑可谓是非常简单了,只需要玩家走一步、电脑走一步,并在八种可能获胜结果中比对就行了,下面让我们一起来看看三子棋的实现。

  注意:本文为模拟游戏实现,代码量两百左右,共有两个源文件+一个头文件。

正文

本程序一共就下面三个文件
三子棋——年轻人的第一款小游戏前言正文总结 
三子棋——年轻人的第一款小游戏前言正文总结 

主函数部分(test.c)

 我们直接从主函数开始!
三子棋——年轻人的第一款小游戏前言正文总结 
 下面看看game(游戏)函数的设计
三子棋——年轻人的第一款小游戏前言正文总结 
//三子棋
#include"game.h"
void menu()
{
	printf("**************************\n");
	printf("********  1.Play  ********\n");
	printf("********  0.Exit  ********\n");
	printf("**************************\n");

}
void game()
{
	char board[ROW][COL] = { 0 };//定义
	init_board(board, ROW, COL);//初始化
	display_board(board, ROW, COL);//打印
	//下棋
	char tmp = 0;
	while (1)
	{
		player_move(board, ROW, COL);//玩家走
		display_board(board, ROW, COL);//打印
		tmp=who_win(board, ROW, COL);//判断
		if (tmp != 'C')
			break;

		computer_move(board, ROW, COL);//电脑走
		display_board(board, ROW, COL);//打印
		tmp=who_win(board, ROW, COL);//判断
		if (tmp != 'C')
			break;
	}
	if (tmp == '*')
		printf("玩家获胜\n");
	else if (tmp == '#')
		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;
}
           
 主函数文件(test.c就介绍完了),下面介绍game.h这个头文件

头文件部分(game.h)

这个头文件是自己建立的,目的就是在主函数源文件(test.c)和功能实现函数(game.c)中搭起一座沟通的桥梁。
三子棋——年轻人的第一款小游戏前言正文总结 
#pragma once
#include<stdio.h>
#include<stdlib.h>

#define ROW 3
#define COL 3

void init_board(char board[][COL],int row,int col);//初始化

void display_board(char board[][COL], int row, int col);//打印

void player_move(char board[][COL], int row, int col);//玩家走

void computer_move(char board[][COL], int row, int col);//电脑走

char who_win(char board[][COL], int row, int col);//判断
           
自定义头文件部分代码量最少,功能也比较简单,如果说test.c是大脑、控制中心,那么game.h就相当于神经系统的一部分,是函数间沟通的桥梁,能对函数起主导作用。

功能实现函数部分(game.c)

此部分是程序运行必不可少的部分,没有它们,程序能跑,但什么都干不了,类似于植人。

本部分函数细节较多,因此我会分开逐个讲解。 

 1.初始化函数

三子棋——年轻人的第一款小游戏前言正文总结 
 初始函数主要就是把整个数组遍历一遍,然后将字符 空格 (' ')赋给每个数组即可。
三子棋——年轻人的第一款小游戏前言正文总结 
void init_board(char board[][COL], int row, int col)//初始化
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';//初始化数组为空格' '
		}
	}
}
           

2.打印棋盘函数

打印棋盘函数需要思考下:什么情况打印 | 和 什么情况打印 --- ,不想清楚这些问题就无法打印出优美的棋盘。
三子棋——年轻人的第一款小游戏前言正文总结 
void display_board(char board[][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)//不打印第三组
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//不打印第三组
					printf("|");
			}
			printf("\n");
		}
	}
}
           

3.玩家移动函数

玩家移动就是让玩家输入坐标,输入坐标有三种情况:非法、占用、成功,依次判断即可,其次要注意不是人人都知道坐标从0开始,因此在使用x、y时要减1,确保坐标不会越界。
三子棋——年轻人的第一款小游戏前言正文总结 
void player_move(char board[][COL], int row, int col)//玩家走
{
	int x = 0;
	int y = 0;
	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] = '*';//落子成功
				break;//跳出循环
			}
			else
				printf("此坐标已被占用,重新输入\n");
		}
		else
			printf("坐标非法,重新输入\n");
	}
}
           

4.电脑移动函数

电脑移动不要太多判断,只需要给电脑一个随机值,一个判断条件。

直到电脑落子成功再跳出即可

三子棋——年轻人的第一款小游戏前言正文总结 
void computer_move(char board[][COL], int row, int col)//电脑走
{
	printf("轮到电脑落子:>");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	printf("电脑已落子\n");
}
           

5.判断输赢函数

这个函数出现于玩家或电脑移动之后,目的就是判断是否已达成胜利条件(共八种),如果达成了,就能跳出game函数中的死循环,结束游戏。
三子棋——年轻人的第一款小游戏前言正文总结 
三子棋——年轻人的第一款小游戏前言正文总结 
 注意:本程序中函数就判断输赢函数和判断和局函数有返回值,一个是char,一个是int
int place(char board[][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 who_win(char board[][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 < row; 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[0][0];//判断正斜

	if (board[0][2] == board[1][1] && 
		board[1][1] == board[2][0] && board[2][0] != ' ')
		return board[0][2];//判断反斜

	if (place(board, ROW, COL) == 1)
		return 'Q';//判断和局

	return 'C';//默认选项
}
           

6.重回game函数

经过game.c中各函数的一顿操作,最终由判断输赢函数携带返回值回到game函数进行判断
三子棋——年轻人的第一款小游戏前言正文总结 

效果展示

让我们直接来看看效果如何:
三子棋——年轻人的第一款小游戏前言正文总结 
可以看到三种情况都能实现,现在只需要将代码进行优化,主要是优化输赢判断部分,使其兼容性更强,以后在玩五子棋时能沿用这套方案。 
 下面我将展示功能实现函数(game.c)的全部代码:
#define _CRT_SECURE_NO_WARNINGS 1	
#include"game.h"

void init_board(char board[][COL], int row, int col)//初始化
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';//初始化数组为空格' '
		}
	}
}

void display_board(char board[][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)//不打印第三组
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)//不打印第三组
					printf("|");
			}
			printf("\n");
		}
	}
}

void player_move(char board[][COL], int row, int col)//玩家走
{
	int x = 0;
	int y = 0;
	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] = '*';//落子成功
				break;//跳出循环
			}
			else
				printf("此坐标已被占用,重新输入\n");
		}
		else
			printf("坐标非法,重新输入\n");
	}
}

void computer_move(char board[][COL], int row, int col)//电脑走
{
	printf("轮到电脑落子:>");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
	printf("电脑已落子\n");
}

int place(char board[][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 who_win(char board[][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 < row; 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[0][0];//判断正斜

	if (board[0][2] == board[1][1] && 
		board[1][1] == board[2][0] && board[2][0] != ' ')
		return board[0][2];//判断反斜

	if (place(board, ROW, COL) == 1)
		return 'Q';//判断和局

	return 'C';//默认选项
}
           

总结 

  我们本次三子棋之旅到这就要结束了,说实在的,三子棋这段代码蕴含逻辑比较简单,唯一需要注意的就是棋盘打印和电脑随机值,只有理解透彻了,代码敲起来才能得心应手!

三子棋——年轻人的第一款小游戏前言正文总结 

继续阅读