2

Me and my friend wrote a simple (but really long) text-based game, which plays in the Windows command prompt. The problem is, that the cmd window does not include any kind of auto-linebreak like it does in Microsoft word, and thus makes the game unplayable. If I wasn't very clear, this is an example on how the game plays now:

You wake up in a dark room. Wherev
er you look, you can't see anythin
g. You try to move, but you can't;
your hands are tied down by the lo
oks of it.

Is there any kind of easy way to fix this? The game is more than 2000 lines long, and thus we'd probably never be able to fix the sentences one-by-one.

Edit: Just to make clear, what I'd like to achieve is the following:

You wake up in a dark room.
Wherever you look, you can't see
anything. You try to move, but
you can't; your hands are tied
down by the looks of it.
Smodics
  • 143
  • 1
  • 11
  • I'm not sure what you want to do, but if all the games does is writing to System.out, then you can use System.setOut(...) to set it to your own PrintStream that redirects it to System.out, only with Linebreaks added. – Florian Schaetz Aug 15 '15 at 12:35
  • And how would one do that? Is there some kind of tutorial on the internet? I'm kind of a beginner in Java. – Smodics Aug 15 '15 at 12:40
  • That depends on what your criteria for the line breaks are... – Florian Schaetz Aug 15 '15 at 12:40
  • Basically the cmd window has a character limit of 80 in each line, and then it continues printing out the text in the next line. My criteria would be the following: In every 80 characters it looks for the last space and prints out a new line instead. Is this possible to achieve? – Smodics Aug 15 '15 at 12:45
  • seems to me like tough to achieve, since you do not have the properties of command prompt window. (font, text dimensions, window dimensions) This sounds lime much more hassle than actually grabbing sample code of text area from some tutorial and redirecting your system outs there. With a little bit of work, you can even make it look like command line prompt if you like. – Vojtěch Kaiser Aug 15 '15 at 12:49
  • @Smodics this is no longer the general case. You can change number of characters per line pretty much everywhere nowadays. – Vojtěch Kaiser Aug 15 '15 at 12:50

3 Answers3

3

Commonly, lines of width 72 are used to make text easily readable, so I advise sticking to this and not trying to work out the width of the text terminal. To achieve proper word wrapping your best option is to rely on Apache WordUtils, which contains the wrap method. Alternatively (if you don't want to download another JAR just for this), just copy its implementation into your project:

/*
 * Copyright 2002-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public static String wrap(String str, int wrapLength, String newLineStr, boolean wrapLongWords) {
    if (str == null) {
        return null;
    }
    if (newLineStr == null) {
        newLineStr = SystemUtils.LINE_SEPARATOR;
    }
    if (wrapLength < 1) {
        wrapLength = 1;
    }
    int inputLineLength = str.length();
    int offset = 0;
    StringBuilder wrappedLine = new StringBuilder(inputLineLength + 32);

    while ((inputLineLength - offset) > wrapLength) {
        if (str.charAt(offset) == ' ') {
            offset++;
            continue;
        }
        int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);

        if (spaceToWrapAt >= offset) {
            // normal case
            wrappedLine.append(str.substring(offset, spaceToWrapAt));
            wrappedLine.append(newLineStr);
            offset = spaceToWrapAt + 1;

        } else {
            // really long word or URL
            if (wrapLongWords) {
                // wrap really long word one line at a time
                wrappedLine.append(str.substring(offset, wrapLength + offset));
                wrappedLine.append(newLineStr);
                offset += wrapLength;
            } else {
                // do not wrap really long word, just extend beyond limit
                spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
                if (spaceToWrapAt >= 0) {
                    wrappedLine.append(str.substring(offset, spaceToWrapAt));
                    wrappedLine.append(newLineStr);
                    offset = spaceToWrapAt + 1;
                } else {
                    wrappedLine.append(str.substring(offset));
                    offset = inputLineLength;
                }
            }
        }
    }

    // Whatever is left in line is short enough to just pass through
    wrappedLine.append(str.substring(offset));

    return wrappedLine.toString();
}
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
2

A very simple example. In your case, you will probably need to store your input until the place for a line break comes in, etc. but I hope you get the basic idea...

public class RedirectPrintStream extends PrintStream {

    private static String NEW_LINE = String.format("%n"); // This creates the system-specific line break (depends on Windows/Linux/etc)

    public RedirectPrintStream(OutputStream out) {
        super(out); 
    }

    @Override
    public void print(String obj) {
        super.print(obj);  // or check here if the obj.length > 80 and add another line break, etc.
        super.print(NEW_LINE);

    }

    public static void main(String[] args) {

        PrintStream old = System.out;
        System.setOut( new RedirectPrintStream(old));

        System.out.print("Hello");
        System.out.print("World"); // will be printed in a new line instead of the same

    }
}

As for the wrapping itself, I would second the already mentioned WordUtils from Apache Commons lang. Should be simple enough.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
  • As far as I understand, biggest problem for OP is, where to break the line, not how. This may help, but finding out how many characters per line there is is crucial for this to work in general. This is not complete answer. – Vojtěch Kaiser Aug 15 '15 at 12:56
  • Ok, added something for that. Personally I would also use Apache Commons Lang for that. No need to write everything from scratch. – Florian Schaetz Aug 15 '15 at 12:59
0

This is not an actual java issue, as tags would suggest, but if you're using System.out as your output, You can:

  1. Change your windows cmd width to fit your needs
  2. According to this link, get your cmd width dynamically. Then, create an object of a class, which would be your output handler. Get the width and save it as a field. Then whenever you want an output, call its method, which would automatically put line breaks to your strings and then call redirect to system.out.
Community
  • 1
  • 1
piezol
  • 915
  • 6
  • 24
  • 1
    The link explains that jline2 can be used, but actually it has a transitive dependency named `jansi` and uses its internal API (removed in the current version on Github). Jansi requires a native DLL to be present on the system. – Marko Topolnik Aug 15 '15 at 12:52