用随机列表中的 2 个值填充 2D 数组(2048 游戏)

Posted

技术标签:

【中文标题】用随机列表中的 2 个值填充 2D 数组(2048 游戏)【英文标题】:Filling 2D Array with 2 values from a random list (2048 Game) 【发布时间】:2020-03-30 17:29:00 【问题描述】:

我正在尝试重新创建 2048 游戏,但我碰到了一堵砖墙并被难住了。我用二维数组制作了我的网格,它似乎工作正常。然后我制作了一种方法来在这个网格/数组中存储一个空白/可用空间列表,以便可以将两个起始数字分配给两个随机可用空间。我的问题是我无法让数字显示在实际网格中。我在下面有我的代码,如果有人能告诉我我哪里出错了,我将不胜感激。抱歉,如果我解释得很糟糕,我对 Java 还是很陌生。

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;

public class Main 
    //Game Board Size Method - Getting User Number to use for dimension of game board
    public static int gameBoardSize() 
        int number = 0;
        int row = 0;
        Scanner in = new Scanner(System.in);
        System.out.println("Welcome to 1024");
        System.out.print("Please select a number between 4 & 8 to determine the size of your game board: "); //Prompt user to select number
        number = in.nextInt(); //Storing number in variable
        if (number >= 4 && number <= 8)  //If number is >= 4 and <= 8
            row = number; //Assign number to row variable
         else 
            System.out.print("Error, please select a number between 4 & 8"); //Error print message
        
        return row; //Return
    

    //Display Game board method - Array for game board grid and to display the grid.
    public static void displayGameBoard(int[][] gameBoard, int gameBoardSize) 
        String divider;
        switch (gameBoardSize) 
            case 5:
                divider = "\n+-----+-----+-----+-----+-----+"; //User Number 5
                break;
            case 6:
                divider = "\n+-----+-----+-----+-----+-----+-----+"; //User Number 6
                break;
            case 7:
                divider = "\n+-----+-----+-----+-----+-----+-----+-----+"; //User Number 7
                break;
            case 8:
                divider = "\n+-----+-----+-----+-----+-----+-----+-----+-----+"; //User Number 8
                break;
            default:
                divider = "\n+----+-----+-----+----+"; //User Number 4
        
        System.out.println(divider); //Printing Divider at top
        for (int i = 0; i < gameBoard.length; i++) 
            for (int j = 0; j < gameBoard[i].length; j++) 
                if (gameBoard[i][j] == 0)  //If both i & j is == 0
                    System.out.print("|     "); //Print this left border
                
                if (j == gameBoard[j].length - 1)  //If 2nd array length -1 (end)
                    System.out.print("|"); //Print end border
                
            

            System.out.println(divider); //Printing Divider at bottom
        
    



    public static int[][] createGameBoard(int userRows) 
        return new int[userRows][userRows]; //Returning rows
    


    //Method to loop through array to find empty space
    public static int[][] findEmptyCells(int[][] gameBoard)  
        int freeCellCount = 0;
        int[][] emptyList = new int[gameBoard.length * gameBoard.length][2];
        for (int i = 0; i < gameBoard.length; i++) 
            for (int j = 0; j < gameBoard[i].length; j++) 
                if (gameBoard[i][j] == 0) 
                    emptyList[freeCellCount][0] = i;
                    emptyList[freeCellCount][1] = j;
                    freeCellCount++;
                
                Random rnd = new Random();
                int rndPair = rnd.nextInt(freeCellCount);
                emptyList[rndPair][0] = i;
                emptyList[rndPair][1] = j;
            
        
        return emptyList;
    

    //Use WASD: W for up, S for Down, A for Left and D for Right
    public static void instructions() 
        System.out.println("How to Play");
        System.out.println("Press W to move up");
        System.out.println("Press S to move down");
        System.out.println("Press A to move left");
        System.out.println("Press D to move right");
    



    public static void main(String[] args) 
        int rows = gameBoardSize();
        int[][] gameBoard = createGameBoard(rows);
        displayGameBoard(gameBoard, rows);
        instructions();
        int[][] findEmptyCells = findEmptyCells(gameBoard);
    

【问题讨论】:

【参考方案1】:

除非您需要使用打印到控制台来创建此游戏 - 我会尽快放弃此方法。在一个并非像动画窗格那样设计的空间中创建像 2048 这样的游戏将会非常困难和令人沮丧。

相反,我会让每个图块都成为一个对象,并对 Java 中的 swing 和 Graphics 进行一些研究。

如果你必须这样做,(顺便说一下,检查你设置网格的方式 - 它不是一致的间距)你必须打印“|”之间的值字符。

有什么聪明的方法可以做到这一点?好吧,您可以创建一个 2D int 数组 int[][],并将所有值存储在游戏板上。然后,您可以遍历 2D 数组中的每个元素,并在您的“|”之间打印它人物。 以下示例适用于任何大小的二维数组。尝试更改您传入的值的数量并注意其行为方式

public class Test 
    private static int[][] temp = new int[][] 0,2, 4,4, 4,16, 3, 0, 128;

    public static void main(String[] args) 
        int rows = temp.length;
        int cols = temp[0].length;

        for (int i = 0; i < rows; i++) 
            // This will resize our row separator for each row
            for (int j = 0; j < cols; j++) 
                System.out.print("+-----");
            

            System.out.print("+\n");

            for (int j = 0; j < cols; j++) 
                System.out.print("|");

                // Here you have to deal with the spacing. You can see that this is ugly.
                // There's definitely better ways to do this, such as using mod
                if (temp[i][j] == 0) System.out.print("     ");
                else if (temp[i][j] < 10) System.out.print("  " + temp[i][j] + "  ");
                else if (temp[i][j] < 100) System.out.print("  " + temp[i][j] + " ");
                else if (temp[i][j] < 1000) System.out.print(" " + temp[i][j] + " ");
            

            System.out.print("|\n");
        

        for (int j = 0; j < cols; j++) 
            System.out.print("+-----");
        

        System.out.print("+\n");
    

上面程序的输出:

+-----+-----+-----+
|     |  2  |  4  |
+-----+-----+-----+
|  4  |  4  |  16 |
+-----+-----+-----+
|  3  |     | 128 |
+-----+-----+-----+

但是还有保持间距正确的问题。您需要考虑数字的长度,因为如果数字为空白,您必须打印正确数量的空格。或者你将不得不使用 replace()...这听起来很混乱。

【讨论】:

令牌,谢谢回复。不幸的是,我需要使用打印控制台来创建它。我知道我的间距仅适用于空白单元格的大小。我现在不知道如何在我的网格/单元格中打印一个数字,所以我还不能解决我的尺寸问题。感谢您的回复,我一定会测试您的代码。【参考方案2】:

要背负@sleepToken 的答案,您可以使用String.format 填充您的输出:

public class Test 
  private static int[][] temp = new int[][] 0,2, 4,4, 4,16, 3, 0, 128;

  public static void main(String[] args) 
      int rows = temp.length;
      int cols = temp[0].length;

      String separator = "+---------------";

      for (int i = 0; i < rows; i++) 
          // This will resize our row separator for each row
          for (int j = 0; j < cols; j++) 
              System.out.print(separator);
          

          System.out.print("+\n");

          for (int j = 0; j < cols; j++) 
            System.out.print(String.format("|%5s%5s%5s", "", temp[i][j], ""));
          

          System.out.print("|\n");
      

      for (int j = 0; j < cols; j++) 
        System.out.print(separator);
      

      System.out.print("+\n");
  

这会像这样填充:

+---------------+---------------+---------------+
|         0     |         2     |         4     |
+---------------+---------------+---------------+
|         4     |         4     |        16     |
+---------------+---------------+---------------+
|         3     |         0     |       128     |
+---------------+---------------+---------------+

可能必须使用填充值,但我所拥有的格式可以很好地播放到 5 位数字。

下面是另一个示例,说明如何根据您希望最大单元格宽度(长度)的长度进行动态填充:

public class Test 
  private static int[][] temp = new int[][] 0,2, 4,4, 4,16, 3, 0, 8;

  public static void main(String[] args) 

    int rows = temp.length;
    int cols = temp[0].length;

    int maxCellLength = 15; //define our cell width

    int longestDigit = longestDigit(temp); //get the length of our longest diget

    if (longestDigit > maxCellLength) maxCellLength = longestDigit + 10; //add extra padding if the longest digit is longer than our cell length

    int leftPad = (maxCellLength - longestDigit) / 2;

    int rightPad = maxCellLength - longestDigit - leftPad;

    String fmt = "|%" + leftPad +"s%" + longestDigit + "s%" + rightPad + "s"; //construct our string format

    String separator = "+" + repeat("-", maxCellLength); //construct the separator

    for (int i = 0; i < rows; i++) 
      // This will resize our row separator for each row
      for (int j = 0; j < cols; j++) 
        System.out.print(separator);
      

      System.out.print("+\n");

      for (int j = 0; j < cols; j++) 
        System.out.print(String.format(fmt, "", temp[i][j], ""));
      

      System.out.print("|\n");
    

    for (int j = 0; j < cols; j++) 
      System.out.print(separator);
    

    System.out.print("+\n");
  


  public static int longestDigit(int[][] arr) 
    int longest = 0;
    for(int i = 0; i < arr.length; i++) 
      for (int j = 0; j < arr[i].length; j++) 
        String intStr = String.valueOf(arr[i][j]);
        if (intStr.length() > longest) longest = intStr.length();
      
    

    return longest;
  

  private static String repeat(String n, int length) 
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < length; i++) 
      sb.append(n);
    
    return sb.toString();
  


【讨论】:

我知道必须有一种方法来智能化我幼稚的 if 语句,哈哈 +1 更新了我的答案以添加更多单元格宽度的动态计算以及填充

以上是关于用随机列表中的 2 个值填充 2D 数组(2048 游戏)的主要内容,如果未能解决你的问题,请参考以下文章

用随机数填充我的数组?

创建并填充2D数组

用 90 行 Haskell 代码实现 2048 游戏

如何用生成器中的值填充 2D Python numpy 数组?

C# 合并重复列表项并将它们的第二个值求和(2D 对象列表)

在 2D JavaScript 数组周围添加填充