五子棋工程心得-----艺果yiguo

本文介绍了五子棋工程的管理框架,包括分级管理与全局变量的处理,并详细解析了网格定点算法和游戏结束判定算法,旨在提高用户体验和游戏的准确性。
摘要由CSDN通过智能技术生成

五子棋工程心得

1.工程框架

1.1分级管理

  • 对于一个工程的编辑来说为了更好的管理所有的应用,main函数中只包括几个工程管理外不要加其他的函数,这样有利于你的层级管理如下:
int main(int argc,char const *argv[])
{
    loop:
    //项目初始化
    project_init();
    //项目运行
    project_run();
    //项目资源回收
    project_uninit();
    
    goto loop;
    return 0;
}
  • 对于不同功能的函数进行分类为初始化、运行、资源回收三个工程函数,让它们分别管理工程里的初始化、运行,资源回收的相应函数。例如:
void project_init()
{
    //初始化lcd
    lcd_init();
    
    //初始化touch
    touch_init();
    
    //棋盘棋子置空
    pieces_init();
}

1.2在工程管理头文件中定义、管理全局变量

这样的作法一般用于多文件全局变量,不建议用于单文件的全局变量,单文件建议用(static修饰)。

/*
    多文件全局变量!
    以及跨文件宏定义!
*/
#ifndef _PROJECT_H_
#define _PROJECT_H_#define quit_game 0xff
#define undraw 0xfe
#define Empty_pieces 0x00
#define NonEmpty_pieces 0x01
#define black 0
#define white 1
#define colorless 0xfd
#define Covered 1
#define unCovered 0
​
​
typedef struct coordinate{
    int x;
    int y;
    int Function_flag;
}Coordinate;
typedef struct piecesdata{
    char pieces[16][16];
    char black_white[16][16];
    char game_progress[16][16];
    char pieces_color;
    char blackcount;
    char whitecount;
}Piecesdata;
​
Coordinate location;
Piecesdata ps;
#endif
/*
    单文件全局变量静态化
*/
static char fd_lcd;

2.算法简析

2.1网格定点算法简析

  • 对于一个触摸屏上的网格点查询附近的点的采用最小距离有两种;坐标做差取最小,i = (x-15)/30;x =
    (i30+15-x)>(i30+45-x)?(i30+45):(i30+15);y坐标也相同的处理。功能当你想点击周围四个点被覆盖的点,由于电容屏的精确度较低,我们需要提高用户的体验感
    做的处理,采用欧拉公式法:x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
    ?(x-30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x-30)));
    /*
        网格定点算法
        location.x,location.y为全局变量
        网格的开始坐标为(175,15)
             结束坐标为(625,465)
*/
#define pow2(x,y) ((x)*(x)+(y)*(y))void location_change_grid()
{
    int x,y;
    x = location.x;
    y = location.y;
    
    if(abs(y-400)>240||abs(x-240) > 240)
    {
        location.Function_flag = undraw;
    }
    else
    {
        int i,j;
        i = (x-15)/30;
        x = (i*30+15-x)>(i*30+45-x)?(i*30+45):(i*30+15);
        j = (y-175)/30;
        y = (j*30+175-y)>(j*30+205-y)?(j*30+205):(j*30+175);
        
        /*
            功能当你想点击周围四个点被覆盖的点,
            由于电容屏的精确度较低,我们需要提高用户
            的体验感 做的处理
        */
        if(ps.pieces[(x-15)/30][(y-175)/30] != Empty_pieces)
        {
            int minx,miny;  
            if(x < location.x && y < location.y) //在相对位置的第一象限
            {
                minx = abs(location.x - x);
                miny = abs(location.y - y);
                x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(x+30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x+30)));
                y = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(pow2((30-minx), miny)<pow2((30-minx), (30-miny))?(y):(y+30)):(y+30));
            }
            else if(x > location.x && y < location.y) //在相对位置的第二象限
            {
                minx = abs(location.x - x);
                miny = abs(location.y - y);
                x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(x-30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x-30)));
                y = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(pow2((30-minx), miny)<pow2((30-minx), (30-miny))?(y):(y+30)):(y+30));
            }
            else if(x > location.x && y > location.y)//在相对位置的第三象限
            {
                minx = abs(location.x - x);
                miny = abs(location.y - y);
                x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(x-30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x-30)));
                y = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(pow2((30-minx), miny)<pow2((30-minx), (30-miny))?(y):(y-30)):(y-30));
            }
            else if(x < location.x && y > location.y)//在相对位置的第四象限
            {
                minx = abs(location.x - x);
                miny = abs(location.y - y);
                x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(x+30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x+30)));
                y = (pow2((30-minx),miny)<pow2(minx, (30-miny))
                    ?(pow2((30-minx), miny)<pow2((30-minx), (30-miny))?(y):(y-30)):(y-30));
            }
            else //其他
            {
                location.Function_flag = undraw;
            }
        }
    }
    location.x = x;
    location.y = y;
}
minx = abs(location.x - x);
miny = abs(location.y - y);
//三点与获取点之间的次进点,前项x为最近点
//采用最小距离公式——欧拉公式
x = (pow2((30-minx),miny)<pow2(minx, (30-miny))
     ?(x-30):(pow2(minx, (30-miny))<pow2((30-minx), (30-miny))?(x):(x-30)));
//同上
y = (pow2((30-minx),miny)<pow2(minx, (30-miny))
     ?(pow2((30-minx), miny)<pow2((30-minx), (30-miny))?(y):(y-30)):(y-30));

2.2判定游戏是否结束

  • 对于五子棋的游戏结束有以有连成五子或以上的子就结束,可能出现的情况是左斜对角,右斜对角,横,竖。分别用函数实现如下的int
    passTop_right(int i,int j,int n,int m) 参数:当前位置为i,j;原位置n,m。
/*
        将棋盘的信息存储在
        typedef struct piecesdata{
            char pieces[16][16];//是否下有棋子
            char black_white[16][16];//是黑子还是白子或无子
            char game_progress[16][16];//是否以及判定过这一个点
            char pieces_color;//当前下子的颜色
            char blackcount;//黑子数
            char whitecount;//白字数
        }Piecesdata;中
*/
#define max(x,y) ((x)>(y)?(x):(y))static char win;int passTop_right(int i,int j,int n,int m)int pass_right(int i,int j,int n,int m)int passBottom_right(int i,int j,int n,int m)int pass_Bottom(int i,int j,int n,int m)int pass(int i, int j, int n, int m);
​
int game_over()
{   
    for(int i = 0;i < 16;i++)
    {
        for(int j = 0;j < 16;j++)
        {
            ps.game_progress[i][j] = 0;
        }
    }
    int count;
    for(int j = 0;j < 16;j++)
    {
        for(int i = 0;i < 16;i++)
        {
            count = 0;
            if(ps.game_progress[i][j] == unCovered)
            {
                count = pass(i, j, i, j);
            }
            if(count >= 5)
            {
                if(ps.black_white[i][j] == black)
                    win = black;
                else
                    win = white;
                location.Function_flag = -1;
                break;
            }
        }
    }   
}
//判断当前位置左上角是否有五子,返回左上方向上的棋子数
int passTop_right(int i,int j,int n,int m)
{
    if(ps.black_white[i][j] == colorless||ps.black_white[i][j]!=ps.black_white[n][m]
        ||i < 0||j < 0||i >= 16||j >= 16)
    {
        return 0;
    }
    return passTop_right(i-1, j+1, n, m)+1;
}
//判断当前位置左角是否有五子,返回左方向上的棋子数
int pass_right(int i,int j,int n,int m)
{
    if(ps.black_white[i][j] == colorless||ps.black_white[i][j]!=ps.black_white[n][m]
        ||i < 0||j < 0||i >= 16||j >= 16)
    {
        return 0;
    }
    return pass_right(i, j+1, n, m)+1;
}
//判断当前位置左下角是否有五子,返回左下方向上的棋子数
int passBottom_right(int i,int j,int n,int m)
{
    if(ps.black_white[i][j] == colorless||ps.black_white[i][j]!=ps.black_white[n][m]
        ||i < 0||j < 0||i >= 16||j >= 16)
    {
        return 0;
    }
    return passBottom_right(i+1, j+1, n, m)+1;
}
//判断当前位置下角是否有五子,返回下方向上的棋子数
int pass_Bottom(int i,int j,int n,int m)
{
    if(ps.black_white[i][j] == colorless||ps.black_white[i][j]!=ps.black_white[n][m]
        ||i < 0||j < 0||i >= 16||j >= 16)
    {
        return 0;
    }
    return pass_Bottom(i+1, j, n, m)+1;
}
//返回所有路径上的最多的个数。
int pass(int i, int j, int n, int m)
{
    int Top_right,right,Bottom_right,Bottom;
    
    Top_right = passTop_right(i, j, n, m);
    
    right = pass_right(i, j, n, m);
    
    Bottom_right = passBottom_right(i, j, n, m);
​
    Bottom = pass_Bottom(i, j, n, m);return (max(Top_right,max(right,max(Bottom,Bottom_right))));
}
2020/7/17 10:27 finish 艺果yiguo

https://pan.baidu.com/s/1300HNo43HgPZwtXF-wt1Qw
提取码:yigu

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值