⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------
//  名称: 用PIC18与触摸屏设计的国际象棋游戏程序
//-----------------------------------------------------------------
//  说明: 本例棋盘下半部分白子为用户方,上半部分黑子为CPU方.
//        案例运行时,用户可通过点击LCD(触摸LCD)与CPU对弈.
//        在每次轮到CPU控制行棋时,其搜索过程会通过虚拟终端显示.
//        CPU将选择最佳方式来操作.
//
//-----------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include "chess.h"
//全局变量
ZPAGE BOARD board;         //棋盘中当前各棋子信息[位置,棋子类型/颜色] 
ZPAGE MASK validmovemask;  //有效移动掩码
ZPAGE MASK capturemask;    //捕获掩码
ZPAGE INT  movecount;      //移动计数
ZPAGE BYTE movetype;       //移动类型NO_MOVE,NORMAL,SAFE,SAFECAPTURE,CAPTURE
ZPAGE BYTE rate;           //移动权重评估值
ZPAGE BYTE piecerate;      //当前棋子的移动方案权重评估
ZPAGE BYTE lastmove;       //上次移动的棋子(用于避免某些棋子连续移动)
//将军与将死
ZPAGE BYTE wh_king_pos[2]; //白方王的位置
ZPAGE BYTE bl_king_pos[2]; //黑方王的位置
ZPAGE BYTE opp_king_pos[2];//对方王的位置
ZPAGE BOOL kingcapture;    //王被将
//王车易位
ZPAGE BYTE wh_base_cont;   //白子底线掩码
ZPAGE BYTE bl_base_cont;   //黑子底线掩码
ZPAGE MASK currcapturemask;//当前捕获掩码
ZPAGE MASK currmovemask;   //当前移动掩码
extern void sleep(int);
//-----------------------------------------------------------------
// 搜索棋子p从当前位置from开始的所有的合法移动
// 搜索结果保存于validmovemask和capturemask
// 两数组分别为该棋子的当前所有可能的移动掩码及捕获掩码
// 该函数所调用的各类棋子的合法移动搜索函数编写在validate.c中
//-----------------------------------------------------------------
void validate(BYTE p,BYTE from[],BOOL piececolour)
{
    switch (p)
    {  


    }
}

//-----------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------
void main()
{ 


 }

//-----------------------------------------------------------------
// 与CPU对弈的象棋游戏
//-----------------------------------------------------------------
void cpuplay()
{ 
   LOC from, to, cpufrom, cputo;  PIECE p;
   BYTE i = 0, j = 0, movefrom, moveto, bestfrom, bestto, illegal = FALSE;
   while(1)
   { 
      //-----------------------------------------------------------
      // 已方移动(已方执白,偶数次由已方移动)
      //-----------------------------------------------------------
      if (((movecount + 1) & 0x01) == 0)
      {  

      }  
      //-----------------------------------------------------------
      // 对方移动(由单片机控制棋子移动,单片机执黑,奇数次由单片机移动)
      // 该移动所涉及的算法是本例程序算法中最复杂的,它需要搜索所有
      // 黑子的所有可能的移动方式,并找出可能最佳的移动方案.
      //-----------------------------------------------------------
      else if (((movecount + 1) & 0x01) == 1)
      {  

      }
    }
 }

//-----------------------------------------------------------------
// 本函数专用于为“黑子”p找出从from位置出发的最佳目标位置序号(0~63)
//-----------------------------------------------------------------
INT getbestpiecemove(BYTE from[])
{
   BYTE i,j,k,tmp,to[2],move,bestmove,curr_pos_rate;
   bestmove = NO_MOVE;
   piecerate = tmp = 0;
   //当前两个掩码数组validmovemask,capturemask内容为本方信息(这里指黑子),
   //在开始搜索对手移动捕获信息时,先将其备份到currmovemask与currcapturemask
   //再将validmovemask,capturemask数组中的掩码字节清0
   for (i = 0; i < 8; i++)
   {  currmovemask[i]    = validmovemask[i];
      currcapturemask[i] = capturemask[i];
      validmovemask[i] = 0x00;
      capturemask[i] = 0x00;
   }
   //通过双重for循环扫描处理“黑子”可能移入的每行(i)中的每个格子(j)
   //评估移入[i,j]格子后的状况:
   //包括NO_MOVE,NORMAL,CAPTURE,SAFE,SAFECAPTURE以及对应的权重值
   for (i = 0; i < 8; i++)
   {   //从掩码字节currmovemask[i]的第0位开始逐位判断
       for (j = 0; j < 8; j++)
       {            
          //如果棋盘格式[i,j]可移入黑子p(从掩码低位开始判断)
          if (currmovemask[i] & 0x01)
          {
             //则开始对黑子p由from位置到[i,j]位置的移动进行评估------
             to[0] = i; to[1] = j; 
             //下面的test_singlemove函数对p由from到to的单次移动进行检测
             //test_simglemove针对假定已处于to位置的黑子p,搜索全盘中的白子,
             //看是否出现"王"被捕获.可能被对方将军时返回FALSE,否则返回TRUE.
             //返回值为TRUE是表示该移动可行(但不代表最优,因为还要对该移动进行评估)
             if (test_singlemove(from,to,board[from[0]][from[1]]))
             { //当前p由from到to(即[i,j])的移动可行时,再进一步对移动进行权重评估         
               //getindex得到目标格子是0~63中的第几个格子(t[0]*8 + t[1])
               move = getindex(to[0],to[1]);
               //移动类型初始设为NORMAL
               movetype = NORMAL;
               //注意:本函数中每调用一次test_singlemove后,validmovemask与capturemask中
               //所保存的都是对方“白子”的掩码,通过该掩码可知道对方的可移入位置.
               //当前循环中黑子是处于位置from的,如果白子掩码中from位置恰好标识
               //白子可移入的黑子所在的from位置,则表示黑子可被白子吃掉
               if ((validmovemask[from[0]] >> from[1]) & 0x01)            
               {  //故加大该移动的权重,使其有可能避免被白子吃掉
                   //(所加的权重为棋子自身权重的1/2)
                  tmp = (board[from[0]][from[1]] & 0x07) / 2;
               }
               //如果白子不能捕获将移入[i,j]位置的黑子p,而黑子p可捕获[i,j]位置的白子,
               //将移动类型设为SAFECAPTURE(可安全捕获)
               if((!((capturemask[i] >> j) & 0x01)) && 
                    ((currcapturemask[i] >> j) & 0x01))    movetype = SAFECAPTURE;
               //否则如果仅仅是黑子可捕获[i,j]位置的白子(白子也能捕获移入[i,j]的黑子)
               //则将移动类型设为CAPTURE(可捕获)
               else if ((currcapturemask[i] >> j) & 0x01)  movetype = CAPTURE;
               //否则如果白子不能捕获将移入[i,j]位置的黑子(黑子亦不能捕获[i,j]位置白子)
               //则将移动类型设为SAFE(是安全的)
               else if (!((capturemask[i] >> j) & 0x01))   movetype = SAFE;
               //根据目标位置to(即[i,j])与指定的理想位置[3,3]的距离(水平+垂直格子数)
               //计算出移到目标位置to的权重值curr_pos_rate
               curr_pos_rate  = ((to[0] > 3) ? to[0] - 3 : 3 - to[0]) +
                                ((to[1] > 3) ? to[1] - 3 : 3 - to[1]);
               //对黑子p由from到to的移动进行进一步评估,累加评估返回权重
               //函数rate_move综合考虑的3项因素分别是:
               //(1) movetype (2) 棋子的价值(棋子符号常量定义) (3) 由from到[3,3]的距离
               tmp += rate_move((board[from[0]][from[1]]),to,curr_pos_rate);
               //如果评估值大于前一移动尝试的评估值piecerate
               if (tmp > piecerate)
               {  //则更新当前棋子可能更佳的移动方式
                  //piecerate保存新的权重,bestmove保存新的目标格子序号(0~63)
                  piecerate = tmp; bestmove = move; 
               }   
               tmp = 0;  
            }
            //清空掩码字节
            for (k = 0; k < 8; k++) validmovemask[k] = capturemask[k] = 0;
         }
         //取得第i行掩码中的下一位(即第j位掩码)
         currmovemask[i] = currmovemask[i] >> 1;
      }
   }
   if (bestmove != NO_MOVE) //显示可能找到的最佳移动路径
   printf("bm : %d,from : %d,%d, rate: %d  movetype : %d\n",
          bestmove,from[0],from[1],piecerate,movetype); 
   return bestmove; //返回目标格子序号(0~63)
 }

//-----------------------------------------------------------------
// test_singlemove(BYTE from[],BYTE to[],PIECE p)
// 该函数对棋子p由from到to位置的一次移动进行检测
// 检查假设棋子p(白子或黑子)由from位置移入to位置时,在不与规则
// 冲突的情况下,"王"是否被将,被将时返回FALSE(表示移动不可行),
// 未被将时返回TRUE(表示移动可行).
// 另外:调用该函数以后validmovemask与capturemask两个掩码数组中保存的
// 全部是对手的掩码信息.(无论返回值如何,该函数最终并不改动棋盘当前格局)
//-----------------------------------------------------------------
BOOL test_singlemove(BYTE from[],BYTE to[],PIECE p)
{  INT i = 0,j = 0; 
   BYTE opp_pos[2];
   PIECE opp_piece,tmpdest;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -