📄 gamepanel.java
字号:
/* * This file is part of MUSoSu. * * MUSoSu is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * MUSoSu is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MUSoSu. If not, see <http://www.gnu.org/licenses/>. */package musUI;import java.awt.AWTException;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.GridLayout;import java.awt.Point;import java.awt.Robot;import java.awt.event.ComponentAdapter;import java.awt.event.ComponentEvent;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.util.Stack;import java.util.Vector;import javax.swing.JPanel;import sudoku.Convert;import sudoku.Sudoku;/** * part of <b>MUSoSu</b> * <p>Class <code>GamePanel</code>is a customised JPanel to contain * one sudoku game board. Provides features such us:</p> * <ul><li>Tooltip of each squares possible values</li> * <li>Mark squares with different colors using mouse right click and unmarking using mouse left click.</li> * <li>Navigation using keyboard arrows</li> * <li>Highlight Column, Box, Line and trace feature</li> * <li>Error highlighting of lines/boxes/columns</li> * <li>Undo-redo functionality</li></ul> * Use loadboard(Sudoku game) to load a sudoku game * @author Visvardis Marios * @version 0.7 */@SuppressWarnings("serial")public class GamePanel extends JPanel{ private boolean showTrace; private boolean showToolTip; private Color highlightColor; private Color squareBackColor; private Color fixedBackColor; private Color errorBackColor; private Color panelBackColor; private Color markColorA, markColorB, markColorC, markColorD; private MStatusPanel mStatus; private MSquare[][] square; private JPanel[] sPanel; private Sudoku game; private Stack<GameAction> undoStack; private Stack<GameAction> redoStack; // Constructor public GamePanel(MStatusPanel status){ this.mStatus = status; status.setVisible(false); undoStack = new Stack<GameAction>(); redoStack = new Stack<GameAction>(); square = new MSquare[9][9]; for(int i = 0; i < 9; i++){ for(int j = 0; j < 9; j++){ square[i][j] = new MSquare(); square[i][j].setName(new String("b" + i + j)); square[i][j].addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent evt){ bKeyPressed(evt); } }); square[i][j].addMouseListener(new MouseAdapter(){ public void mouseEntered(MouseEvent evt){ mouseEnteredSquare(evt); } public void mouseExited(MouseEvent evt){ mouseExitedSquare(evt); } public void mouseClicked(MouseEvent evt){ mouseClickedSquare(evt); } }); } } sPanel = new JPanel[9]; for(int i = 0; i < 9; i++){ sPanel[i] = new JPanel(); sPanel[i].setLayout(new GridLayout(3, 3));// sPanel[i].setBackground(Color.WHITE); sPanel[i].setBorder(null); } int spInd = 0, tmp = 0; for(int i = 0; i < 9; i++){ for(int j = 0; j < 9; j++){ sPanel[spInd].add(square[i][j]); tmp++; if(tmp == 9){ spInd++; tmp = 0; } } } setLayout(new GridLayout(3, 3, 5, 5)); setBackground(Color.black); for(int i = 0; i < 9; i++){ add(sPanel[i]); } addComponentListener(new ComponentAdapter(){ public void componentResized(ComponentEvent evt){ panelResized(); } }); } public void loadBoard(Sudoku game){ this.game = game; int i, j; String txt; int num; int posi; for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ posi = Convert.koutiaToIndex(i, j); num = game.get(posi); if(num != 0){ txt = String.valueOf(num); if(game.isFixed(posi)){ square[i][j].setFixed(true); square[i][j].setFont(new Font("Arial", Font.BOLD, 18)); square[i][j].setDefaultBackgroundColor(fixedBackColor); }else square[i][j].setDefaultBackgroundColor(squareBackColor); }else{ txt = ""; square[i][j].setDefaultBackgroundColor(squareBackColor); } square[i][j].setText(txt); } } setBackground(panelBackColor); undoStack.clear(); redoStack.clear(); setVisible(true); } /** * Gets the Vector of possible values of a Cell * and creates a tooltip for each square in the panel * */ private void refreshPossibles(){ int i, j; Vector<Integer> pv; int index; int c; String ps = new String(); for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ index = Convert.koutiaToIndex(i, j); pv = game.getPossibles(index); ps = ""; for(c = 0; c < pv.size(); c++){ ps += String.valueOf(pv.get(c).intValue()) + " "; } square[i][j].setToolTipText(ps); if(!showToolTip) square[i][j].setToolTipText(null); } } } // Error Highlight methods // These methods are called by handleError // to highlight the line/column/box that has a square // with a value that conflicts with the user input /** * <code>errorHighlightLine</code> * @param lineNumber the line to be highlighted */ private void errorHighlightLine(int lineNumber){ int[] kout = new int[2]; int i; for(i = 0; i < 9; i++){ kout = Convert.kartesToKoutia(lineNumber, i); square[kout[0]][kout[1]].setBackgroundColor(errorBackColor); } } /** * <code>errorHighlightColumn</code> * @param columnNumber the column to be highlighted */ private void errorHighlightColumn(int columnNumber){ int[] kout = new int[2]; int i; for(i = 0; i < 9; i++){ kout = Convert.kartesToKoutia(i, columnNumber); square[kout[0]][kout[1]].setBackgroundColor(errorBackColor); } } /** * <code>errorHighlightBox</code> * @param boxNumber */ private void errorHighlightBox(int boxNumber){ for(int i = 0; i < 9; i++) square[boxNumber][i].setBackgroundColor(errorBackColor); } private void highlightLine(int lineNumber){ int[] kout = new int[2]; int i; for(i = 0; i < 9; i++){ kout = Convert.kartesToKoutia(lineNumber, i); if(!square[kout[0]][kout[1]].isMarked()) square[kout[0]][kout[1]].setBackgroundColor(highlightColor); } } private void highlightColumn(int columnNumber){ int[] kout = new int[2]; int i; for(i = 0; i < 9; i++){ kout = Convert.kartesToKoutia(i, columnNumber); if(!square[kout[0]][kout[1]].isMarked()) square[kout[0]][kout[1]].setBackgroundColor(highlightColor); } } private void highlightBox(int boxNumber){ for(int i = 0; i < 9; i++) if(!square[boxNumber][i].isMarked()) square[boxNumber][i].setBackgroundColor(highlightColor); } private void handleError(int index){ int[] err = new int[2]; int[] kartes = new int[2]; int[] koutia = new int[2]; kartes = Convert.indexToKartes(index); koutia = Convert.indexToKoutia(index); err = game.whyICant(); switch(err[0]){ case 1: errorHighlightLine(kartes[0]); break; case 2: errorHighlightColumn(kartes[1]); break; case 3: errorHighlightBox(koutia[0]); break; } } /** * <code>restoreBackColors</code> * <p>Restores the colors of the squares to their initial state, * after a highlight or an errorHighlight</p> */ private void restoreBackColors(){ for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++){ square[i][j].restoreBackgroundColor(); } } /** * <code>doParty</code> * <p>Creates the finished game effects. Currently only changes * the gamePanel background color.</p> * <p>TODO: Play a sound</p> * <p>TODO: popup something</p> */ private void doParty(){ setBackground(new Color(241, 184, 184)); } /** * <code>markSquare</code> * <p>marks a square with a color, depending on markKind</p> * @param index is the number of the square to be marked * @param markKind is an integer with possible values 1-4 that correspond to 4 preset mark colors * TODO this code can be made cleaner e.g. replace the switch */ public void markSquare(int index, int markKind){ Color c; int[] kout = new int[2]; kout = Convert.indexToKoutia(index); switch(markKind){ case 1: c = markColorA; square[kout[0]][kout[1]].mark(c);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -