FiveLogic.java
上传用户:gyyuli
上传日期:2013-07-09
资源大小:3050k
文件大小:18k
源码类别:

J2ME

开发平台:

Java

  1. import java.io.PrintStream;
  2. import java.util.*;
  3. import javax.microedition.lcdui.Canvas;
  4. public class FiveLogic
  5. {
  6.     private FiveCanvas cavFive;
  7.     private int borderSize;
  8.     private boolean computerFirst;
  9.     private int degree;
  10.     public static int STONE_NONE = 0;
  11.     public static int STONE_COMPUTER = 1;
  12.     public static int STONE_MAN = 2;
  13.     private int stones[][];
  14.     private Dot lastDot;
  15.     private int stoneCounter[];
  16.     private Stack steps;
  17.     private Dot triedDot;
  18.     private static int GAIN_BY_COMPUTER = 5;
  19.     private static int GAIN_BY_NONE = 1;
  20.     private boolean endOfGame;
  21.     private boolean computerWon;
  22.     private boolean thinking;
  23.     private Random rnd;
  24.     public FiveLogic(FiveCanvas cav, int bSize, boolean cFirst, int deg)
  25.     {
  26.     
  27.         borderSize = 11;
  28.         computerFirst = true;
  29.         degree = 1;
  30.         cavFive = cav;
  31.         borderSize = bSize;
  32.         computerFirst = cFirst;
  33.         degree = deg;
  34.         stones = new int[bSize][bSize];
  35.         for(int r = 0; r < borderSize; r++)
  36.         {
  37.             for(int c = 0; c < borderSize; c++)
  38.                 stones[r][c] = 0;
  39.         }
  40.         lastDot = new Dot(borderSize);
  41.         stoneCounter = new int[3];
  42.         stoneCounter[1] = 0;
  43.         stoneCounter[2] = 0;
  44.         stoneCounter[0] = borderSize * borderSize;
  45.         steps = new Stack();
  46.         triedDot = new Dot(-1, -1);
  47.         endOfGame = false;
  48.         thinking = false;
  49.         rnd = new Random();
  50.     }
  51.     public int[][] stones()
  52.     {
  53.         return stones;
  54.     }
  55.     public Dot lastDot()
  56.     {
  57.         return lastDot;
  58.     }
  59.     public Dot triedDot()
  60.     {
  61.         return triedDot;
  62.     }
  63.     public boolean gameEnd()
  64.     {
  65.         return endOfGame;
  66.     }
  67.     public boolean computerWon()
  68.     {
  69.         return computerWon;
  70.     }
  71.     public boolean thinking()
  72.     {
  73.         return thinking;
  74.     }
  75.     private boolean endOfGame()
  76.     {
  77.         endOfGame = false;
  78.         for(int r = 0; r < borderSize; r++)
  79.         {
  80.             for(int c = 0; c < borderSize; c++)
  81.             {
  82.                 if(stones[r][c] == 0 || existNLineWithMinFree(r, c, 5, 0, -1) == -1)
  83.                     continue;
  84.                 endOfGame = true;
  85.                 computerWon = stones[r][c] == 1;
  86.                 break;
  87.             }
  88.             if(endOfGame)
  89.                 break;
  90.         }
  91.         if(endOfGame)
  92.             cavFive.notifyGameEnd();
  93.         return endOfGame;
  94.     }
  95.     public void manGo(int row, int col)
  96.     {
  97.         if(row >= 0 && row < borderSize && col >= 0 && col < borderSize && stones[row][col] == 0)
  98.         {
  99.             goAt(row, col, 2);
  100.             if(endOfGame())
  101.             {
  102.                 if(computerWon)
  103.                     cavFive.setStatus("你输了!", 0xff0000, 2);
  104.                 else
  105.                     cavFive.setStatus("u4F60u8D62u4E86!", 65280, 1);
  106.             } else
  107.             {
  108.                 computerGo();
  109.             }
  110.         }
  111.     }
  112.     private void goAt(int row, int col, int playerStone)
  113.     {
  114.         int lastRow = lastDot.row;
  115.         int lastCol = lastDot.col;
  116.         stones[row][col] = playerStone;
  117.         lastDot.setRowCol(row, col);
  118.         cavFive.repaintAt(lastRow, lastCol);
  119.         cavFive.repaintAt(row, col);
  120.         switch(playerStone)
  121.         {
  122.         case 1: // '01'
  123.             stoneCounter[1]++;
  124.             break;
  125.         case 2: // '02'
  126.             stoneCounter[2]++;
  127.             break;
  128.         }
  129.         stoneCounter[0]--;
  130.         if(steps.size() > 10)
  131.             steps.removeElementAt(0);
  132.         steps.push(new Dot(row, col));
  133.     }
  134.     public boolean undo()
  135.     {
  136.         if(steps.size() >= 3)
  137.         {
  138.             Dot d = new Dot();
  139.             d.copyFrom((Dot)steps.pop());
  140.             stones[d.row][d.col] = 0;
  141.             cavFive.repaintAt(d.row, d.col);
  142.             d.copyFrom((Dot)steps.pop());
  143.             stones[d.row][d.col] = 0;
  144.             cavFive.repaintAt(d.row, d.col);
  145.             d.copyFrom((Dot)steps.peek());
  146.             lastDot.copyFrom(d);
  147.             cavFive.repaintAt(d.row, d.col);
  148.             return true;
  149.         } else
  150.         {
  151.             return false;
  152.         }
  153.     }
  154.     public void computerGo()
  155.     {
  156.         cavFive.setStatus("思考中...", 0, 0);
  157.         cavFive.serviceRepaints();
  158.         think();
  159.     }
  160.     public void think()
  161.     {
  162.         thinking = true;
  163.         Dot dc = null;
  164.         if((dc = thinkInNumber(1, 5)) == null && (dc = thinkInNumber(2, 5)) == null && (dc = to4B(1)) == null && (dc = to4B(2)) == null && (dc = toDouble4S_3B_2N1B(1, true)) == null && (dc = toDouble4S_3B_2N1B(2, true)) == null && (dc = toDouble4S_3B_2N1B(1, false)) == null && (dc = toDouble4S_3B_2N1B(2, false)) == null && (dc = toSingle4S_3B_2N1B(1)) == null)
  165.             dc = toSingle4S_3B_2N1B(2);
  166.         if(dc == null)
  167.             dc = maxGainedDot();
  168.         if(dc == null || stoneCounter[0] == 0)
  169.         {
  170.             cavFive.setStatus("平局!", 255, 3);
  171.         } else
  172.         {
  173.             System.out.println("Gone!");
  174.             goAt(dc.row, dc.col, 1);
  175.             if(endOfGame())
  176.             {
  177.                 if(computerWon)
  178.                     cavFive.setStatus("u4F60u8F93u4E86!", 0xff0000, 2);
  179.                 else
  180.                     cavFive.setStatus("u4F60u8D62u4E86 !", 65280, 1);
  181.             } else
  182.             {
  183.                 cavFive.setStatus("u8BF7u4E0Bu5B50...");
  184.             }
  185.         }
  186.         thinking = false;
  187.     }
  188.     private Dot to4B(int playerStone)
  189.     {
  190.         if(stoneCounter[playerStone] < 3)
  191.             return null;
  192.         Dot dot = null;
  193.         int maxGain = 0;
  194.         for(int r = 1; r < borderSize - 1; r++)
  195.         {
  196.             for(int c = 1; c < borderSize - 1; c++)
  197.                 if(stones[r][c] == 0)
  198.                 {
  199.                     int cd[] = connectedIn8D(playerStone, r, c);
  200.                     int ed[] = expandedIn8D(playerStone, r, c);
  201.                     for(int i = 0; i < 4; i++)
  202.                         if(ed[i] > cd[i] && ed[i + 4] > cd[i + 4] && cd[i] + cd[i + 4] + 1 >= 4)
  203.                         {
  204.                             int gain = gainAt(r, c);
  205.                             if(gain > maxGain || gain > 0 && gain == maxGain && randomTrue())
  206.                             {
  207.                                 maxGain = gain;
  208.                                 dot = new Dot(r, c);
  209.                             }
  210.                         }
  211.                 }
  212.         }
  213.         return dot;
  214.     }
  215.     private Dot toSingle4S_3B_2N1B(int playerStone)
  216.     {
  217.         if(stoneCounter[playerStone] < 2)
  218.             return null;
  219.         Dot dot = null;
  220.         for(int r = 0; r < borderSize; r++)
  221.         {
  222.             for(int c = 0; c < borderSize; c++)
  223.             {
  224.                 if(stones[r][c] != 0 || find4S_3B_2N1BAt(r, c, playerStone, -1) == -1)
  225.                     continue;
  226.                 dot = new Dot(r, c);
  227.                 break;
  228.             }
  229.             if(dot != null)
  230.                 break;
  231.         }
  232.         return dot;
  233.     }
  234.     private Dot toDouble4S_3B_2N1B(int playerStone, boolean only4S)
  235.     {
  236.         if(stoneCounter[playerStone] < 4)
  237.             return null;
  238.         Dot dot = null;
  239.         for(int rTest = 0; rTest < borderSize; rTest++)
  240.         {
  241.             for(int cTest = 0; cTest < borderSize; cTest++)
  242.             {
  243.                 if(stones[rTest][cTest] != 0)
  244.                     continue;
  245.                 int cd[] = connectedIn8D(playerStone, rTest, cTest);
  246.                 if(cd[0] + cd[1] + cd[2] + cd[3] + cd[4] + cd[5] + cd[6] + cd[7] <= 0)
  247.                     continue;
  248.                 triedDot.setRowCol(rTest, cTest);
  249.                 stones[rTest][cTest] = playerStone;
  250.                 boolean found = false;
  251.                 int dFirst = find4S_3B_2N1B(playerStone, -1, rTest, cTest, only4S);
  252.                 if(dFirst != -1 && find4S_3B_2N1B(playerStone, dFirst, rTest, cTest, false) != -1)
  253.                     found = true;
  254.                 stones[rTest][cTest] = 0;
  255.                 triedDot.setRowCol(-1, -1);
  256.                 if(!found)
  257.                     continue;
  258.                 dot = new Dot(rTest, cTest);
  259.                 break;
  260.             }
  261.             if(dot != null)
  262.                 break;
  263.         }
  264.         return dot;
  265.     }
  266.     private int find4SAt(int row, int col, int playerStone, int exceptDirection)
  267.     {
  268.         int dFond = -1;
  269.         int cd[] = connectedIn8D(playerStone, row, col);
  270.         int ed[] = expandedIn8D(playerStone, row, col);
  271.         for(int d = 0; d < 4; d++)
  272.         {
  273.             if(d == exceptDirection || stones[row][col] != playerStone)
  274.                 continue;
  275.             int nConnect = cd[d] + cd[d + 4] + 1;
  276.             int nFree1 = ed[d] - cd[d];
  277.             int nFree2 = ed[d + 4] - cd[d + 4];
  278.             boolean b4S = nConnect >= 4 && (nFree1 >= 1 || nFree2 >= 1);
  279.             if(!b4S)
  280.                 continue;
  281.             dFond = d;
  282.             break;
  283.         }
  284.         return dFond;
  285.     }
  286.     private int find4S_3B_2N1BAt(int row, int col, int playerStone, int exceptDirection)
  287.     {
  288.         int dFond = -1;
  289.         int cd[] = connectedIn8D(playerStone, row, col);
  290.         int ed[] = expandedIn8D(playerStone, row, col);
  291.         for(int d = 0; d < 4; d++)
  292.         {
  293.             if(d == exceptDirection)
  294.                 continue;
  295.             if(stones[row][col] == playerStone)
  296.             {
  297.                 int nConnect = cd[d] + cd[d + 4] + 1;
  298.                 int nFree1 = ed[d] - cd[d];
  299.                 int nFree2 = ed[d + 4] - cd[d + 4];
  300.                 boolean b4S = nConnect >= 4 && (nFree1 >= 1 || nFree2 >= 1);
  301.                 boolean b3B = nConnect >= 3 && nFree1 >= 1 && nFree2 >= 1;
  302.                 if(b4S || b3B)
  303.                 {
  304.                     dFond = d;
  305.                     break;
  306.                 }
  307.             }
  308.             if(stones[row][col] != 0)
  309.                 continue;
  310.             int nFree1 = ed[d] - cd[d];
  311.             int nFree2 = ed[d + 4] - cd[d + 4];
  312.             boolean b2N1 = cd[d] >= 2 && cd[d + 4] >= 1 || cd[d] >= 1 && cd[d + 4] >= 2;
  313.             boolean bSFree = nFree1 >= 1 && nFree2 >= 1;
  314.             if(!b2N1 || !bSFree)
  315.                 continue;
  316.             dFond = d;
  317.             break;
  318.         }
  319.         return dFond;
  320.     }
  321.     private int find4S_3B_2N1B(int playerStone, int exceptDirection, int rTest, int cTest, boolean only4S)
  322.     {
  323.         int dFond = -1;
  324.         int rMin = rTest - 3;
  325.         if(rMin < 0)
  326.             rMin = 0;
  327.         int rMax = rTest + 3;
  328.         if(rMax > borderSize)
  329.             rMax = borderSize;
  330.         int cMin = cTest - 3;
  331.         if(cMin < 0)
  332.             cMin = 0;
  333.         int cMax = cTest + 3;
  334.         if(cMax > borderSize)
  335.             cMax = borderSize;
  336.         for(int r = rMin; r < rMax; r++)
  337.         {
  338.             for(int c = cMin; c < cMax; c++)
  339.             {
  340.                 if(stones[r][c] != playerStone && stones[r][c] != 0)
  341.                     continue;
  342.                 if(only4S)
  343.                     dFond = find4SAt(r, c, playerStone, exceptDirection);
  344.                 else
  345.                     dFond = find4S_3B_2N1BAt(r, c, playerStone, exceptDirection);
  346.                 if(dFond != -1)
  347.                     break;
  348.             }
  349.             if(dFond != -1)
  350.                 break;
  351.         }
  352.         return dFond;
  353.     }
  354.     private Dot thinkInNumber(int stonePlayer, int nl)
  355.     {
  356.         if(stoneCounter[stonePlayer] < nl - 1)
  357.             return null;
  358.         int maxGain = 0;
  359.         Dot dot = null;
  360.         for(int r = 0; r < borderSize; r++)
  361.         {
  362.             for(int c = 0; c < borderSize; c++)
  363.             {
  364.                 int gain = thinkInNumberAt(stonePlayer, r, c, nl);
  365.                 if(gain > maxGain || gain > 0 && gain == maxGain && randomTrue())
  366.                 {
  367.                     maxGain = gain;
  368.                     dot = new Dot(r, c);
  369.                 }
  370.             }
  371.         }
  372.         return dot;
  373.     }
  374.     private int thinkInNumberAt(int lineStone, int row, int col, int nl)
  375.     {
  376.         int lines = 0;
  377.         int otherGain = 0;
  378.         if(stones[row][col] == 0)
  379.         {
  380.             int cd[] = connectedIn8D(lineStone, row, col);
  381.             int ed[] = expandedIn8D(lineStone, row, col);
  382.             for(int i = 0; i < 4; i++)
  383.                 if(ed[i] + ed[i + 4] + 1 >= 5)
  384.                 {
  385.                     int l = cd[i] + cd[i + 4] + 1;
  386.                     if(l >= nl)
  387.                         lines++;
  388.                     else
  389.                         otherGain += 2 ^ l;
  390.                 }
  391.         }
  392.         return lines > 0 ? lines * 32 + otherGain : 0;
  393.     }
  394.     private int[] expandedIn8D(int stone, int row, int col)
  395.     {
  396.         int ed[] = new int[8];
  397.         for(int d = 0; d < 8; d++)
  398.             ed[d] = expandedIn1D(stone, row, col, d);
  399.         return ed;
  400.     }
  401.     private int expandedIn1D(int stone, int row, int col, int direction)
  402.     {
  403.         int n = 0;
  404.         int cn = 0;
  405.         Dot d = new Dot(row, col);
  406.         while(cn < 4) 
  407.         {
  408.             d.copyFrom(forwardOneStep(d, direction));
  409.             if(!d.inBorder(borderSize))
  410.                 break;
  411.             int st = stones[d.row][d.col];
  412.             if(st == 0)
  413.                 cn++;
  414.             if(st != stone && st != 0)
  415.                 break;
  416.             n++;
  417.         }
  418.         return n;
  419.     }
  420.     private Dot maxGainedDot()
  421.     {
  422.         Dot dotWithMaxGain = null;
  423.         int maxGain = 0;
  424.         for(int r = 0; r < borderSize; r++)
  425.         {
  426.             for(int c = 0; c < borderSize; c++)
  427.             {
  428.                 int gain = gainAt(r, c);
  429.                 if(gain > maxGain || gain > 0 && gain == maxGain && randomTrue())
  430.                 {
  431.                     maxGain = gain;
  432.                     dotWithMaxGain = new Dot(r, c);
  433.                 }
  434.             }
  435.         }
  436.         return dotWithMaxGain;
  437.     }
  438.     private int gainAt(int row, int col)
  439.     {
  440.         if(stones[row][col] == 0)
  441.         {
  442.             int gain = 0;
  443.             for(int d = 0; d < 8; d++)
  444.             {
  445.                 int gd = gainAtDirection(row, col, d);
  446.                 if(gd == 0)
  447.                     gain >>= 2;
  448.                 else
  449.                     gain += gd;
  450.             }
  451.             if(gain < 1)
  452.                 gain = 1;
  453.             return gain;
  454.         } else
  455.         {
  456.             return 0;
  457.         }
  458.     }
  459.     private int gainAtDirection(int row, int col, int direction)
  460.     {
  461.         int gain = 0;
  462.         Dot d = new Dot(row, col);
  463.         int step = 0;
  464.         do
  465.         {
  466.             d.copyFrom(forwardOneStep(d, direction));
  467.             step++;
  468.             if(!d.inBorder(borderSize))
  469.                 break;
  470.             int stone = stones[d.row][d.col];
  471.             if(stone == 2)
  472.                 break;
  473.             int gainByStone = stone == 1 ? 5 : 1;
  474.             gain += gainByStep(step) * gainByStone;
  475.         } while(true);
  476.         return gain;
  477.     }
  478.     private int gainByStep(int step)
  479.     {
  480.         int gain = (borderSize - step) / 2;
  481.         if(gain < 1)
  482.             gain = 1;
  483.         return gain;
  484.     }
  485.     private int exist2N1(int row, int col, int playerStone, int exceptDirection)
  486.     {
  487.         int cd[] = connectedIn8D(playerStone, row, col);
  488.         int ed[] = expandedIn8D(playerStone, row, col);
  489.         int existDirection = -1;
  490.         for(int i = 0; i < 4; i++)
  491.         {
  492.             if(i == exceptDirection || (cd[i] < 2 || cd[i + 4] < 1) && (cd[i] < 1 || cd[i + 4] < 2) || (ed[i] - cd[i]) + (ed[i + 4] - cd[i + 4]) <= 0)
  493.                 continue;
  494.             existDirection = i;
  495.             break;
  496.         }
  497.         return existDirection;
  498.     }
  499.     private int existNLineWithMinFree(int row, int col, int n, int minFree, int exceptDirection)
  500.     {
  501.         int stone = stones[row][col];
  502.         int cd[] = connectedIn8D(stone, row, col);
  503.         int ed[] = expandedIn8D(stone, row, col);
  504.         int existDirection = -1;
  505.         for(int i = 0; i < 4; i++)
  506.         {
  507.             if(i == exceptDirection || cd[i] + cd[i + 4] + 1 < n || (ed[i] - cd[i]) + (ed[i + 4] - cd[i + 4]) < minFree)
  508.                 continue;
  509.             existDirection = i;
  510.             break;
  511.         }
  512.         return existDirection;
  513.     }
  514.     private int[] connectedIn8D(int stone, int row, int col)
  515.     {
  516.         int cd[] = new int[8];
  517.         for(int d = 0; d < 8; d++)
  518.             cd[d] = connectedIn1D(stone, row, col, d);
  519.         return cd;
  520.     }
  521.     private int connectedIn1D(int stone, int row, int col, int direction)
  522.     {
  523.         int n = 0;
  524.         Dot d = new Dot(row, col);
  525.         do
  526.         {
  527.             d.copyFrom(forwardOneStep(d, direction));
  528.             if(d.inBorder(borderSize) && stones[d.row][d.col] == stone)
  529.                 n++;
  530.             else
  531.                 return n;
  532.         } while(true);
  533.     }
  534.     private Dot forwardOneStep(Dot d, int direction)
  535.     {
  536.         int r = d.row;
  537.         int c = d.col;
  538.         switch(direction)
  539.         {
  540.         case 0: // ''
  541.             c++;
  542.             break;
  543.         case 1: // '01'
  544.             r--;
  545.             c++;
  546.             break;
  547.         case 2: // '02'
  548.             r--;
  549.             break;
  550.         case 3: // '03'
  551.             r--;
  552.             c--;
  553.             break;
  554.         case 4: // '04'
  555.             c--;
  556.             break;
  557.         case 5: // '05'
  558.             r++;
  559.             c--;
  560.             break;
  561.         case 6: // '06'
  562.             r++;
  563.             break;
  564.         case 7: // '07'
  565.             r++;
  566.             c++;
  567.             break;
  568.         }
  569.         return new Dot(r, c);
  570.     }
  571.     private boolean randomTrue()
  572.     {
  573.         return rnd.nextInt() % 2 == 0;
  574.     }
  575. }